【问题标题】:Extending service stack authentication - populating user session with custom user auth meta data扩展服务堆栈身份验证 - 使用自定义用户身份验证元数据填充用户会话
【发布时间】:2023-03-13 02:43:01
【问题描述】:

我正在尝试扩展 Service Stack 的身份验证和注册功能。我的身份验证和注册工作正常,但是我需要为每个用户添加一些自定义数据。从 Service Stack 的文档和其他各种帖子中,我发现您可以使用 UserAuth 表中内置的 MetaData 列添加自己的数据。

我创建了一个 CustomAuthRepository,所以我可以设置 UserAuth 的元数据属性,这是我的自定义 repo:

public class CustomAuthRepository : OrmLiteAuthRepository, IUserAuthRepository
{
    public UserAuth CreateUserAuth(UserAuth newUser, string password)
    {
        newUser.Set(new LoginInfo
        {
            IsActive = false,
            PasswordNeedsReset = true
        });
        return base.CreateUserAuth(newUser, password);
    }
}

这对于设置元数据非常有用,我最终在 UserAuth 表的元数据列中得到了 LoginInfo 对象的序列化版本。

现在我要做的是,当用户进行身份验证时,我需要根据一些元数据更改 AuthResponse。例如,如果一个用户还没有被激活,我想返回一个带有属性IsActive = get value from custom meta data的AuthResponse

如果我可以将自定义元数据放入 AuthSession,我想我可以做到这一点。这样,在我的自定义凭据身份验证提供程序中,我可以根据 AuthSession 中的内容更改响应对象:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
    {
        var customUserAuthSession = (CustomUserAuthSession)session;

        if (!customUserAuthSession.LoginInfo.IsActive)
        {
            return new
            {
                UserName = customUserAuthSession.UserName,
                IsActive = customUserAuthSession.LoginInfo.IsActive
            };
        }

        var isAuthenticated = base.Authenticate(authService, session, request);

        return isAuthenticated;
    } 
}

我这样做的方式是否正确,还是有更好的方式来存储和检索自定义元数据?

如何根据用户的自定义元数据更改 AuthResponse?

如何将我的自定义元数据放入 AuthSession?

编辑 我越来越接近我想要做的事情。在我的 CustomAuthSession OnAuthenticated() 方法中:

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        var customUserAuthSession = (CustomUserAuthSession) session;

        var userAuth = authService.ResolveService<IUserAuthRepository>().GetUserAuth(session, null);
        customUserAuthSession.LoginInfo = userAuth.Get<LoginInfo>();

        authService.SaveSession(customUserAuthSession);

        base.OnAuthenticated(authService, session, tokens, authInfo);
    }

我正在重新获取 UserAuth 并使用我需要的数据填充会话。基于自定义用户会话的服务堆栈documentation,您需要在使用一些自定义数据填充会话后保存会话。我正在这样做,但它似乎并没有节省。 在我的 CustomCredentialsAuthProvider, Authenticate 方法中,我没有看到我添加到会话中的自定义数据。

编辑 我上面第一次编辑的问题是用户通过了身份验证,然后我们进入 CustomAuthSession 代码,在那里我可以检查它们是否处于活动状态。如果它们不活跃,我需要将它们注销,这并不理想。

我发现我可以在自定义 CredentialsAuthProvider 的 Authenticate 方法中完成所有这些操作。

    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
    {
        var userAuthRepo = authService.ResolveService<IUserAuthRepository>();
        var userAuth = userAuthRepo.GetUserAuthByUserName(request.UserName);
        var loginInfo = userAuth.Get<LoginInfo>();

        if (!loginInfo.IsActive)
        {
            return new CustomAuthResponse
            {
                UserName = userAuth.UserName,
                ResponseStatus = new ResponseStatus("500"),
                IsActive = loginInfo.IsActive
            };
        }

        var authResponse = (AuthResponse)base.Authenticate(authService, session, request);

        return authResponse;
    }

当请求进来时,我可以使用请求中的用户名来获取 UserAuth,并检查用户是否为 IsActive。如果没有,那么我可以在 Service Stack 对它们进行身份验证之前返回一些错误。

我认为这对于我正在尝试做的事情来说已经足够好了。我应该能够向客户端返回一个错误,说明用户未处于活动状态。

如果有人有更简洁的方法来做到这一点,那就太好了。

【问题讨论】:

  • 感谢未阅读该链接的链接。不幸的是,他没有展示如何从 UserAuth 表中的元数据列获取/设置自定义元数据。他确实在 CustomCredentialsAuthProvider 的 OnAuthenticated 方法中向自定义用户会话添加了一些自定义数据,但他的示例显示为“some_firstname_from_db”。如果我能弄清楚如何从数据库中再次获取用户,我可以在这个方法中填充会话。虽然看起来不是很干净,因为当这个方法被称为服务堆栈时,我的用户已经验证了他们的信用并调用了这个方法 post auth
  • 还有其他链接。如果你没有找到他们,herehereherehere 大多数人都活跃在 SO-servicestack 中,所以也许稍后再回答你的问题。
  • 我已经浏览了他们在服务堆栈 git hub 页面上与身份验证功能有关的所有示例,到目前为止还没有运气,但我会继续寻找。谢谢你的链接,我也看看那些。

标签: servicestack


【解决方案1】:

到目前为止,这是我的答案。它有效,我可以做我想做的事,但我很想听听一些服务堆栈人员关于这是否是解决此问题的最佳方法。

保存自定义元数据

创建一个子类OrmLiteAuthRepository 的新类。就我而言,我只想使用 Service Stack 内置的 Sql 数据库持久性并让它创建所需的表。

重新实现 CreateUserAuth 方法以保存任何自定义元数据:

    public UserAuth CreateUserAuth(UserAuth newUser, string password)
    {
        newUser.Set(new AccountStatus
        {
            IsActive = false,
            PasswordNeedsReset = true
        });
        return base.CreateUserAuth(newUser, password);
    }

获取自定义元数据

创建一个继承 CredentialsAuthProvider 的新类。覆盖 Authenticate 方法。

    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
    {
        var userAuthRepo = authService.ResolveService<IUserAuthRepository>();
        var userAuth = userAuthRepo.GetUserAuthByUserName(request.UserName);
        var accountStatus= userAuth.Get<AccountStatus>();

        if (!accountStatus.IsActive)
        {
            throw new InvalidOperationException(string.Format("User {0} is not activated.", request.UserName));
        }
        if (!accountStatus.PasswordNeedsReset)
        {
            throw new InvalidOperationException("Your password needs to be reset before you can login.");
        }

        var authResponse = (AuthResponse)base.Authenticate(authService, session, request);

        return authResponse;
    }

当身份验证请求进入此方法时,获取 UserAuth 和自定义元数据。如果用户处于非活动状态,或者他们的密码需要重置,则抛出带有错误消息的 InvalidOperationException。

在我的客户端应用程序的登录控制器中,我可以检查从服务返回的错误消息,并将用户重定向到某个页面,说明帐户尚未激活,或者需要重置他们的密码才能进行身份验证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    相关资源
    最近更新 更多