从客户端进行身份验证后,ServiceStack会话未保存

时间:2018-06-14 07:37:06

标签: c# .net servicestack

我已经实现了自定义身份验证提供程序(CredentialsAuthProvider)来验证自己。这里的一切都很完美。我通过ASP.NET客户端应用程序中的以下代码进行身份验证。

var res = Client.Post(new Authenticate
{
    provider = CredentialsAuthProvider.Name,
    UserName = "admin",
    Password = "topsecret",
    RememberMe = true
});

我的自定义CredentialsAuthProvider中的TryAuthenticate被调用,如果正确则返回true,然后调用IHttpResult OnAuthenticated。效果很好。

在我的OnAuthenticated方法中,我然后设置会话的某些属性的值。所以我做了这样的事情:

public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
{
    try
    {
        // Save the browser cookie.
        if (authService.Request is IHttpResponse httpRes)
            httpRes.Cookies.AddPermanentCookie(HttpHeaders.XUserAuthId, session.UserAuthId);

        session.DisplayName = "MyName";
        session.IsAuthenticated = true;

        // Save the user session object (ServiceStack stores it in the in-memory cache).
        authService.SaveSession(session, TimeSpan.FromHours(5));

        return base.OnAuthenticated(authService, session, tokens, authInfo);
    }
    catch (Exception ex)
    {
        return new HttpResult(HttpStatusCode.ExpectationFailed);
    }
}

此外,直到现在一切都很完美。 现在,如果我想访问需要身份验证的DTO(在我的示例中为Products),我仍然会获得Unauthorized。即使我刚认证并保存了我的会话。

var response = Client.Get(new GetProducts());

我可以看到我的自定义AuthUserSession中的方法IsAuthorized被调用,但查看基本属性(AuthUserSession),我可以看到我之前分配的属性(DisplayName,IsAuthorized) )仍有默认值。 enter image description here

问题:为什么我在OnAuthenticated中分配的属性未被保存?

非常感谢!

编辑:我意识到当我使用它时:

using (JsonServiceClient disposableClient = new JsonServiceClient("http://localhost:24131"))
{
    var res = disposableClient.Post(new Authenticate
    {
        provider = CredentialsAuthProvider.Name,
        UserName = "admin",
        Password = "topsecret",
        RememberMe = true
    });

    var response = disposableClient.Get(new GetProducts());
}

而不是将我的JsonServiceClient用作私有类成员,它可以工作。但我不想每次尝试访问资源时都要进行身份验证。这种行为的原因是什么?

1 个答案:

答案 0 :(得分:2)

大多数自定义AuthProvider都是不必要的,并且已由OnAuthenticated()添加,HttpHeaders.XUserAuthId添加IsAuthenticated=true Cookie,设置public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo) { session.DisplayName = "MyName"; return base.OnAuthenticated(authService, session, tokens, authInfo); } 并保存会覆盖现有的会话,所以基本上是您的自定义Impl应该简化为:

OnSaveSession()

如果你想改变会话的持续时间,你可以覆盖AppHost中的public override void OnSaveSession(IRequest httpReq,IAuthSession session,TimeSpan? expiresIn=null) => base.OnSaveSession(httpReq, session, TimeSpan.FromHours(5)); ,只要会话被保存在ServiceStack的任何地方,就会被调用:

Dispose()

此外,您不必JsonServiceClient var client = new JsonServiceClient("http://localhost:24131"); var response = client.Post(new Authenticate { //Client libs usually don't have access to CredentialsAuthProvider provider = "credentials", UserName = "admin", Password = "topsecret", RememberMe = true }); has no effect。所以你的客户端代码就是:

var response = client.Get(new GetProducts());

使用ServiceClient进行身份验证会在客户端实例上填充Session Cookies,然后您就可以使用该stored in the registered ICacheClient进行经过身份验证的请求:

urn:iauthsession:{sessionId}

请注意,会话为distributed caching provider,因此,如果您的App域重新启动,则会丢失所有会话。要在应用重新启动时保留用户会话,您可以使用stateless Auth Provider like JWT(即除内存之外的任何缓存提供程序)或使用API Key Auth ProviderSession Cookies are being sent

如果您收到UnAuthenticated Response并且您的应用程序尚未重新启动(清除存储在内存缓存中的所有会话),请使用像Fiddler或WireShark这样的数据包/ http嗅探器查看原始HTTP Headers以检查相同的still exists in the cache和经过身份验证的用户会话create your own iterator位于:

{sessionId}

ss-pid.paragraphs Cookie的值。