8

嗨,我是使用 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 };
    }
}

这是应用主机:

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 ,一切都会按预期工作,所以现在问题是为什么。

4

1 回答 1

23

首先查看 wiki 文档

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

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

如果您不确定是什么,您应该参考RequiredRole 源代码作为主要权威来了解它是如何工作的。RequiredRole只是一个请求过滤器属性,它在每个具有该属性的服务之前运行。

RequiredRole 属性只是调用您的session.HasRole()方法,如下所示

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

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

注册和实现 CustomUserSession

Social BootstrapApi 项目确实实现了它自己的CustomSession,它在此处注册但没有覆盖实现,因此它使用基本AuthUserSession.HasRole()HasRole()中的内置实现,它看起来像 Roles 集合,以查看用户是否具有指定的在他们的 Session POCO 中的作用:

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

由 AuthUserRepository 填充的会话属性

Roles属性(以及用户会话上的大多数其他属性)由您指定的 AuthUserRepository 填充,例如,如果您使用OrmLiteAuthRepository就像SocialBootstrapApi在这里所做的那样,那么 Roles 属性将保留在UserAuth RDBMS的Roles列中。根据 AuthUserRepository,您使用 UserAuth / UserOAuthProvider POCO 在 OrmLite 中存储为 RDBMS 表或在 Redis 中存储为文本 blob 等。

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

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

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

这些服务确实要求具有管理员角色的用户已经过身份验证。您可以通过手动更改特定用户的UserAuth.Role列以包含值“Admin”来执行此操作。相反,Social Bootstrap API 项目通过处理OnAuthenticated()CustomUserSession上的事件来执行此操作,该事件只是检查是否在 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 }
    });
}
于 2012-08-23T17:10:00.173 回答