【问题标题】:ServiceStack web services securityServiceStack 网络服务安全
【发布时间】:2012-08-19 04:09:47
【问题描述】:

您好,我是使用 Servicestack 的新手,已经下载了他们非常全面的 bootstrapapi 示例并正在使用它,但仍然遇到一些问题。问题在于安全性,发生的情况是我在尝试访问受保护的服务时遇到 405 错误。使用身份验证服务似乎我正在正确地进行身份验证。请帮忙解释一下。这是代码:

public class Hello
{
    public string Name { get; set; }
}

public class AuthHello
{
    public string Name { get; set; }
}

public class RoleHello
{
    public string Name { get; set; }
}
public class HelloResponse
{
    public string Result { get; set; }
}

服务:

public class HelloService : ServiceBase<Hello> 
{
    //Get's called by all HTTP Verbs (GET,POST,PUT,DELETE,etc) and endpoints JSON,XMl,JSV,etc
    protected override object Run(Hello request)
    {
        return new HelloResponse { Result = "Hello, Olle är en ÖL ål " + request.Name };
    }
}

[Authenticate()]
public class AuthHelloService : RestServiceBase<AuthHello>
{
    public object Execute(Hello request)
    {
        return new HelloResponse { Result = "Hello, " + request.Name };
    }
}

[RequiredRole("Test")]
public class RoleHelloService : RestServiceBase<RoleHello>
{
    public object Execute(Hello request)
    {
        return new HelloResponse { Result = "Hello, " + request.Name };
    }
}

这里是 AppHost:

public class HelloAppHost : AppHostBase
    {
        //Tell Service Stack the name of your application and where to find your web services

        public HelloAppHost() : base("Hello Web Services", typeof(HelloService).Assembly) { }

        public override void Configure(Container container)
        {

            //Register all Authentication methods you want to enable for this web app.
        Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] {new CustomCredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
            }));
        container.Register<ICacheClient>(new MemoryCacheClient() { FlushOnDispose = false });

            //register user-defined REST-ful urls
            Routes
              .Add<Hello>("/hello")
              .Add<Hello>("/hello/{Name}")
              .Add<AuthHello>("/AuthHello")
              .Add<RoleHello>("/RoleHello");
        }
    }

更新

如果您将 : RestServiceBase 替换为 : ISevice,一切都会按预期工作,所以现在问题是为什么。

【问题讨论】:

  • 另外,我在美化代码块以便于阅读时遇到了困难,并遵循了降价帮助,但它似乎并不适用。 在每个代码块之前。

标签: web-services security servicestack


【解决方案1】:

先查看 wiki 文档

我将首先阅读 ServiceStack 的 Authentication Wiki 中的文档,以更好地了解 ServiceStack 的身份验证如何工作。 wiki 中有很多文档,所以如果您不确定某些内容,您应该首先参考。这是一个社区 wiki,如果您认为它可以帮助其他人,请随时扩展那里的内容。

如果行为不清楚,请参考源代码中的实现

如果你不确定什么是你应该refer to the RequiredRole source code 作为主要权威,因为它是如何工作的。 RequiredRole 只是一个 Request Filter Attribute,它在每个具有该属性的服务之前运行。

RequiredRole 属性只是将您的session.HasRole() 方法称为seen here

public bool HasAllRoles(IAuthSession session)
{
    return this.RequiredRoles
        .All(requiredRole => session != null
            && session.HasRole(requiredRole));
}

因为它只是调用您的会话,如果您有自定义会话,您可以覆盖 session.HasRole() 的实现。

注册和实现 CustomUserSession

Social BootstrapApi 项目确实实现了它自己的 CustomSession,它 registers here 但没有覆盖 HasRole() 实现,因此它使用基础 AuthUserSession.HasRole() 中的内置实现,它看起来就像 Roles 集合查看用户在其 Session POCO 中是否具有指定角色:

public virtual bool HasRole(string role)
{
    return this.Roles != null && this.Roles.Contains(role);
}

由 AuthUserRepository 填充的会话属性

Roles 属性(以及用户会话上的大多数其他属性)由您指定的 AuthUserRepository 填充,例如如果您使用OrmLiteAuthRepositorySocialBootstrapApi does here 一样,则Roles 属性将保留在UserAuth RDBMS tableRoles 列中。根据您使用的 AuthUserRepository,UserAuth / UserOAuthProvider POCO 在 OrmLite 中存储为 RDBMS 表或在 Redis 中存储为文本 blob 等。

使用 AssignRoles / UnAssignRoles 服务管理角色和权限

因此,要让用户拥有所需的角色(以及通过的授权),它应该将此角色添加到其 UserAuth 数据库行条目中。 ServiceStack 的AuthFeature 包含两个用于管理用户权限和角色的服务:

最初如何赋予某人管理员角色

这些服务确实需要 user with the Admin Role 已经过身份验证。 为此,您可以手动更改特定用户的 UserAuth.Role 列以包含值“Admin”。相反,Social Bootstrap API 项目通过处理其CustomUserSession 上的OnAuthenticated() 事件来执行此操作,该事件只是检查是否在 Web.Config 中声明了经过身份验证的用户名,如果是,则调用 AssignRoles 服务,为经过身份验证的用户提供管理员角色:

if (AppHost.Config.AdminUserNames.Contains(session.UserAuthName)
    && !session.HasRole(RoleNames.Admin))
{
    var assignRoles = authService.ResolveService<AssignRolesService>();
    assignRoles.Execute(new AssignRoles {
        UserName = session.UserAuthName,
        Roles = { RoleNames.Admin }
    });
}

【讨论】:

  • 感谢您及时详细的回复!事实证明,问题实际上在于继承。当我删除 :RestServiceBase 并仅将 :IService 用于所有服务时,一切都按预期工作,包括安全性。有没有什么地方我可以阅读正确的用法,因为这让我困惑了一天半。
  • 理想情况下,您应该始终使用 ServiceBase / RestServiceBase ,除非有您不想使用的原因,例如您想实现自己的异常处理。 ServiceBase 对所有动词都有 1 个实现,其中 RestServiceBase 允许您为每个动词指定一个 impl。一些与此相关的文档:github.com/ServiceStack/ServiceStack/wiki/… 以及更多关于它的提及 github.com/ServiceStack/ServiceStack/wiki/SOAP-support - 如果您认为可以节省其他人的时间,请考虑扩展现有文档。
  • 哇,我怎么会错过那个维基。回答了我的每一个问题,包括我没有发布的几个问题。另外,解释了为什么在我的测试中 RestServiceBase 对我不起作用,因为我使用不正确。非常感谢。
  • 嘿,神话,角色和权限之间的(实际)区别是什么?它似乎是 Session 上的一对多关系?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-21
相关资源
最近更新 更多