2

我已经实现了一个自定义身份验证提供程序 (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());

我可以看到我的IsAuthorized自定义 AuthUserSession 中的方法被调用,但是查看基础 (AuthUserSession) 的属性,我可以看到我之前分配的属性 (DisplayName, IsAuthorized) 仍然具有它们的默认值。在此处输入图像描述

问题:为什么我分配的属性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 作为私有类成员,而是工作。但是我不想每次尝试访问资源时都进行身份验证。这种行为的原因是什么?

4

1 回答 1

2

您的大部分自定义 AuthProvider 是不必要的,并且已经添加,OnAuthenticated()它添加了HttpHeaders.XUserAuthIdCookie、设置IsAuthenticated=true和保存覆盖现有会话的 Session,因此基本上您的自定义 Impl 应该减少为:

public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
{
    session.DisplayName = "MyName";    
    return base.OnAuthenticated(authService, session, tokens, authInfo);
}

如果您想更改会话的持续时间,您可以OnSaveSession()在 AppHost 中覆盖,只要会话保存在 ServiceStack 中的任何位置,就会调用它:

public override void OnSaveSession(IRequest httpReq,IAuthSession session,TimeSpan? expiresIn=null) 
    => base.OnSaveSession(httpReq, session, TimeSpan.FromHours(5));

你也不必which has no effectDispose()。所以你的客户代码就是: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
});

使用 ServiceClient 进行身份验证会在该客户端实例上填充会话 Cookie ,然后您可以使用它来发出经过身份验证的请求:

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

请注意,Session存储在已注册的 ICacheClient 中,因此如果您的 App Domain 重新启动,它将丢失所有会话。要在 App 重新启动时保留用户会话,您可以使用分布式缓存提供程序(即除内存之外的任何缓存提供程序)或使用无状态的 Auth Provider,如 JWTAPI Key Auth Provider

如果您收到未经身份验证的响应并且您的应用程序尚未重新启动(清除存储在内存缓存中的所有会话),请使用 Fiddler 或 WireShark 等数据包/http 嗅探器查看原始 HTTP 标头以检查相同的会话正在发送 Cookie,并且经过身份验证的用户会话仍然存在于缓存中:

urn:iauthsession:{sessionId}

您的cookie{sessionId}的价值在哪里。ss-pid

于 2018-06-14T12:11:36.147 回答