Как проверить, действителен ли токен доступа или нет? - PullRequest
0 голосов
/ 27 июня 2019

В приведенном ниже коде я ищу обновить маркер доступа, если срок его действия истек.Но ничего не работает.Я попытался отладить с точкой останова в ответе на возврат строки, но эта точка останова не сработает.

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 Ответ

1 голос
/ 27 июня 2019

Обычный способ обновить токен по истечении срока действия - использовать данные об истечении срока действия, поступающие из конечной точки токена с ответом токена. Вы можете кэшировать токен для этого интервала, и каждый раз, когда вам нужно установить канал-носитель, вы сначала пытаетесь получить его из кэша. По истечении срока действия токена кеш возвращает ноль, поэтому вы запрашиваете новый токен и снова его кешируете.
Пожалуйста, смотрите пример, основанный на статье Доминика Байера. Вам нужно будет установить пакет 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;
    }
}
...