如何跨身份验证维护会话信息

时间:2014-09-12 15:50:57

标签: session authentication servicestack

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

现在想要在用户通过身份验证之前在会话中存储一些信息(想想购物车)。但是,当用户稍后登录时,我们会丢失该信息。查看documentation中的代码是有道理的:

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

当用户登录时,身份验证将删除现有会话。当旧登录是有效用户时,您需要确保它已完全注销。但是,当当前会话未经过身份验证时,似乎没有太多理由这样做。

我一直在查看自定义会话工厂,但这对我没有帮助,因为正如() => new AuthUserSession()所示,创建新会话时没有任何上下文可供使用。如果没有办法在那里举行旧会议,我就无法复制任何信息。

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

是否有更清晰的方式在身份验证中传输信息?无论使用何种AuthProvider,最好是有效的。

1 个答案:

答案 0 :(得分:2)

虽然在身份验证后重新创建了Typed Sessions,但Permanent and Temporary Session Ids本身保持不变,这使您可以使用ServiceStack的动态 SessionBag 来存储有关您可以在服务中设置的用户:

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 Session Events中的动态会话包:

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

使用新的GetSessionBag()和便捷ISession Get/Set extension methods在ServiceStack的下一个 v4.0.32 + 中访问Session包会更好一些,这样可以让您重写以上内容:

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;
}