如何检查访问令牌是否有效?

时间:2019-06-27 09:25:08

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

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

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

1 个答案:

答案 0 :(得分: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;
    }
}