【问题标题】:How to check whether the access token is valid or not?如何检查访问令牌是否有效?
【发布时间】:2019-11-09 07:01:57
【问题描述】:

在下面的代码中,如果访问令牌已过期,我希望更新它。但没有任何效果。我尝试在行返回响应上使用断点进行调试,但该断点不会触发。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response = null;
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
            response = await base.SendAsync(request, cancellationToken);

            if (response.StatusCode != HttpStatusCode.Unauthorized)
                return response;

            var tokenResponse = _tokenGenerator.GetAccessToken(accessTokenInfo).Result;
            if (tokenResponse != null)
            {
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResponse);
                response = await base.SendAsync(request, cancellationToken);
            }

            return response;
        }

【问题讨论】:

  • 在过期时更新令牌的常用方法是使用过期数据,该数据来自带有令牌响应的令牌端点。您只需在该时间间隔内缓存令牌,每次需要设置承载时检查它是否仍在缓存中。如果没有,请要求一个新的。等等等等。
  • 任何示例代码都可以继续前进吗?
  • @RuardvanElburg 我需要使用客户端凭据流来完成。所以我不需要刷新令牌。我将使用客户端 ID 和密码来完成。但是我的实际问题没有解决,这是作为问题提出的
  • @d_f 它的网络托管 api 及其现在的工作。我忘记将端口更改为 localhost。但无论如何,如果我的令牌已过期,我的响应状态为未经授权,所以现在我想知道未经授权错误的实际原因。如何获得?
  • 再一次:最好预先检查,而不是事后处理错误。所以只需坚持_accessTokenValidity = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn); 之类的内容,并在每次请求之前检查。当DateTime.UtcNow 超过您保留的值时,请求一个新的令牌(并更新_accessTokenValidity

标签: .net-core identityserver4 access-token sendasync mockhttpmessagehandler


【解决方案1】:

在过期时更新令牌的常用方法是使用过期数据,来自带有令牌响应的令牌端点。您可以缓存该时间间隔的令牌,并且每次需要设置承载时,您首先尝试从缓存中获取它。当令牌过期时,缓存会返回 null,因此您请求一个新的令牌并再次缓存它。
请参阅 Dominick Baier 基于the article 的示例。如果尚未安装,则需要安装 IdentityModel nuget 包。

public class TokenClientOptions
{
    public string Address { get; set; }
    public string ClientId { get; set; }
    public string ClientSecret { get; set; }
}

public class TokenClient 
{
    private const string AccessTokenCacheKey = "access_token";

    public HttpClient Client { get; }
    public TokenClientOptions Options { get; }
    public ILogger<TokenClient> Logger { get; }
    public IDistributedCache Cache { get; }


    public TokenClient(HttpClient client, IOptions<TokenClientOptions> options,
            IDistributedCache cache,
            ILogger<TokenClient> logger)
    {
         Client = client;
         Options = options.Value;
         Cache = cache;
         Logger = logger;
    }


    public async Task<string> GetToken()
    {
         var token = Cache.GetString(AccessTokenCacheKey);
         if (token != null)
                return token;

         var response = await Client.
             RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
         {
                Address = Options.Address,
                ClientId = Options.ClientId,
                ClientSecret = Options.ClientSecret
         });

         Cache.SetString(AccessTokenCacheKey, response.AccessToken,
                new DistributedCacheEntryOptions()
                    {AbsoluteExpirationRelativeToNow = 
                           TimeSpan.FromSeconds(response.ExpiresIn)});
         return response.AccessToken;
     }
}

public static class Extensions
{
    public static void AddTokenClient(this IServiceCollection services) {
        services.Configure<TokenClientOptions>(options =>
        {
             options.Address = "https://demo.identityserver.io/connect/token";
             options.ClientId = "client";
             options.ClientSecret = "secret";
        });

        services.AddDistributedMemoryCache();
        services.AddHttpClient<TokenClient>();
    }
}

然后在您的Startup.ConfigureServices 中添加:services.AddTokenClient();

之后,您可以将 TokenClient 注入您的 API 控制器并像在上面的示例中一样使用它:

public class TestController : Controller
{
    public TokenClient TokenClient { get; }

    public TestController(TokenClient tokenClient) => TokenClient = tokenClient;

    public async Task<HttpResponseMessage> Index()
    {
        var request = new HttpRequestMessage(
            HttpMethod.Get, "https://demo.identityserver.io/api/test");
        var accessToken = await TokenClient.GetToken();
        request.SetBearerToken(accessToken);
        var client = HttpClientFactory.Create();
        var response = await client.SendAsync(request, new CancellationToken());
        return response;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 2011-04-20
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多