0

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

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

1 回答 1

1

过期时更新令牌的常用方法是使用过期数据,来自带有令牌响应的令牌端点。您可以缓存该时间间隔的令牌,每次需要设置承载时,您首先尝试从缓存中获取它。当令牌过期时,缓存返回 null,因此您请求一个新的令牌并再次缓存它。
请参阅基于Dominick Baier的文章的示例。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;
    }
}
于 2019-06-27T20:33:02.710 回答