如何通过身份验证维护会话信息 [英] How to maintain session information across authentication

查看:142
本文介绍了如何通过身份验证维护会话信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将ServiceStack身份验证与自定义会话对象一起使用.我已经使用不同的身份验证提供程序进行了所有设置,并且一切正常.

I using ServiceStack authentication with a custom session object. I've got everything set up with different authentication providers and everything is working fine.

现在想要在验证用户身份之前将一些信息存储在会话中(请考虑购物车).但是,当用户稍后登录时,我们会丢失该信息.查看文档中的代码,这很有意义:

Now a want to store some information in the session before the user is authenticated (Think shopping cart). But we loose that information when the user logs in later. Looking at the code in the documentation this makes sense:

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
  new IAuthProvider[] { 
    new BasicAuthProvider(), //Sign-in with Basic Auth
    new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
  }));

每当用户登录时,身份验证都会删除现有会话.当旧登录名是有效用户时,这很有意义,您需要确保已完全注销.但是,当当前会话未通过身份验证时,似乎没有太多理由进行认证.

The authentication removes the existing session whenever a user logs in. This makes sense when the old login is a valid user, you want to make sure it's fully logged out. However when the current session isn't authenticated there doesn't seem to be much reason to do so.

我一直在寻找自定义会话工厂,但这对我没有帮助,因为如() => new AuthUserSession()所示,创建新会话时没有任何上下文可使用.如果没有办法进行旧会话,那么我将无法复制任何信息.

I've been looking at a custom session factory, but that doesn't help me because as () => new AuthUserSession() shows, there isn't any context to use when creating the new session. Without a way to get the old session there I've got no way to copy any information.

我可以通过覆盖AuthProvider.Authenticate()来解决它,并在调用base之前获取所需的信息.但这意味着在我们使用的每个身份验证提供程序以及将来可能使用的身份验证提供程序中都这样做.真的感觉不像是正确的解决方案.

I can work around it by overriding AuthProvider.Authenticate() and grab the required information before calling base. But that means doing so in every authentication provider we use and the ones we might use in the future. That doesn't really feel like the correct solution.

是否存在更干净的方式来通过身份验证携带信息?不管使用哪种AuthProvider,最好都能工作.

Is there a cleaner way to carry information across the authentication? Preferably something which works regardless of the AuthProvider used.

推荐答案

类型化会话在身份验证后重新创建,永久和临时会话ID 本身保持不变,这使您可以使用ServiceStack的动态 SessionBag 存储有关用户的信息,您可以通过以下方式在服务中设置用户: /p>

Whilst the Typed Sessions are re-created after authenticating, the Permanent and Temporary Session Ids themselves remain the same which lets you use ServiceStack's dynamic SessionBag to store information about a user which you can set in your Services with:

public class UnAuthInfo
{
    public string CustomInfo { get; set; }
}

public class MyServices : Service
{
    public object Any(Request request)
    {
        var unAuthInfo = SessionBag.Get<UnAuthInfo>(typeof(UnAuthInfo).Name) 
            ?? new UnAuthInfo();
        unAuthInfo.CustomInfo = request.CustomInfo;
        SessionBag.Set(typeof(UnAuthInfo).Name, unAuthInfo);
    }
}

然后,您可以在您的自定义AuthUserSession 会话事件与:

You can then access the dynamic Session Bag in your Custom AuthUserSession Session Events with:

public class CustomUserSession : AuthUserSession
{
    [DataMember]
    public string CustomInfo { get; set; }

    public override void OnAuthenticated(IServiceBase service, IAuthSession session, 
        IAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        var sessionBag = new SessionFactory(service.GetCacheClient())
            .GetOrCreateSession();
        var unAuthInfo = sessionBag.Get<UnAuthInfo>(typeof(UnAuthInfo).Name);
        if (unAuthInfo != null)
            this.CustomInfo = unAuthInfo.CustomInfo;
    }
}

v4.0.32 +中的新会话API

使用新的 ISession Get/Set扩展方法,这样您就可以像这样重写上面的内容:

New Session API's in v4.0.32+

Accessing the Session bag will be a little nicer in next v4.0.32+ of ServiceStack with the new GetSessionBag() and convenience ISession Get/Set extension methods which will let you rewrite the above like:

public object Any(Request request)
{
    var unAuthInfo = SessionBag.Get<UnAuthInfo>() ?? new UnAuthInfo();
    unAuthInfo.CustomInfo = request.CustomInfo;
    SessionBag.Set(unAuthInfo);
}

//...

public override void OnAuthenticated(IServiceBase service, IAuthSession session, 
    IAuthTokens tokens, Dictionary<string, string> authInfo)
{
    var unAuthInfo = service.GetSessionBag().Get<UnAuthInfo>();
    if (unAuthInfo != null)
        this.CustomInfo = unAuthInfo.CustomInfo;
}

这篇关于如何通过身份验证维护会话信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆