6

我将 Refit 库与我的 Xamarin 表单项目一起使用来发送 API 请求。它工作得很好,但是当访问令牌过期时会出现问题。

当访问令牌过期时,我从服务器收到 401 错误,正如预期的那样。然后我调用 Identity Server 以发出新的访问令牌,但我在重新提交 API 请求时遇到了困难。我仍然收到未经授权的错误。感谢一些帮助。

我创建了一个 AuthenticatedHttpClientHandler 类来处理令牌。

public class AuthenticatedHttpClientHandler : HttpClientHandler
{
    private readonly string _token;

    public AuthenticatedHttpClientHandler(string token ) 
    {
        _token = token;       
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var auth = request.Headers.Authorization;
        if (auth != null && !string.IsNullOrWhiteSpace(_token))
        {
            request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, _token);
        }
        else
        {
            request.Headers.Remove("Authorization");
        }
        var result = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
        if (result.StatusCode == System.Net.HttpStatusCode.Unauthorized )
        {
            IdSrvApiService idsrvApiService = new IdSrvApiService();
            RefreshTokenService refreshTokneService = new RefreshTokenService(idsrvApiService);

            if( Settings.RefreshToken != ""){
                var newToken = await refreshTokneService.RefreshAccessToken(Priority.Background).ConfigureAwait(false);
                TokenHelper.CacheToken(newToken);
                request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, Settings.AccessToken);
                return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                return result;
            }
        }
        else
        {
            return result;
        }
    }
}
4

3 回答 3

3

我建议检查发送的原始请求,以查看刷新令牌后发送的请求是否发送了正确的标头。

您也有可能在第二次尝试时发送了错误的令牌。确认 in 中的值newToken是通过Settings.AccessToken

于 2018-01-14T23:28:17.363 回答
2

检查您的刷新令牌服务是否在 http 正文帖子上发送正确的标头和参数。

标题:

  • 接受:应用程序/json

身体:

  • grant_type : refresh_token
  • client_id :您的客户 ID(如果适用)
  • client_secret :您的客户端密码(如果适用)
  • refresh_token :获取访问令牌时返回的刷新令牌属性(refresh_token)

确保您在正文标头请求( https://stackoverflow.com/a/5665663/4738253或使用 FormUrlEncodedContent 来创建和编码内容中传递正确的 Content-Type (application/x-www-form-urlencoded))。

于 2018-01-17T12:48:16.817 回答
2

有时我会遇到同样的错误。它更有可能发生,因为服务器和客户端之间的时间差。当我收到此错误时,我强制用户注销。

但我从不尝试刷新 Token。在您的代码中,您想要刷新令牌,但您使用 access_token 发送请求。也许这可能是你的错。

 var newToken = await refreshTokneService.RefreshAccessToken(Priority.Background).ConfigureAwait(false);

我认为,您的这种方法有问题。

于 2018-01-16T08:49:37.887 回答