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