Мы используем нулевую базовую версию шаблона с приложением форм xamarin.
В последнее время мы заметили, что в некоторых случаях, когда истек токен доступа в мобильном приложении, несколько вызовов API получат ответ 401, приводящий к получению нового маркера доступа с использованием маркера обновления.
Похоже, это происходит в основном при вызове двух или более методов API в InitializeAsyn c в пределах модели представления. AbpApiClient, кажется, устанавливает заголовок Authorization для всех вызовов API заранее.
Первый метод определяет, что срок действия AccessToken истек, и, таким образом, устанавливает AuthenticateResult.AccessToken с новым AccessToken, который был возвращен методом RefreshToken. Поскольку Header.Authorization уже был установлен для других методов, следующий метод будет делать то же самое (отправка просроченного AccessToken на сервер и т. Д.)
Мы тестируем с перемещением SemaphoreSlim из HandleAuthorizedResponse для SendAsyn c, чтобы убедиться, что первый метод получает возможность определить, что срок действия AccessToken истек до того, как следующий метод попадет в SendAsyn c. Мы не уверены, является ли это верным решением, так как теперь SendAsyn c всегда доступен только для одного метода, независимо от того, истек ли срок действия AccessToken - да или нет.
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
var tokenManager = IocManager.Instance.IocContainer.Resolve<IAccessTokenManager>();
if (tokenManager.IsUserLoggedIn)
{
var accessToken = tokenManager.GetAccessToken();
request.Headers.Authorization = new AuthenticationHeaderValue(AuthorizationScheme, accessToken);
}
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized &&
HasBearerAuthorizationHeader(request))
{
return await HandleUnauthorizedResponse(request, response, cancellationToken);
}
return response;
}
finally
{
_semaphore.Release();
}
}
private async Task<HttpResponseMessage> HandleUnauthorizedResponse(HttpRequestMessage request, HttpResponseMessage response, CancellationToken cancellationToken)
{
var tokenManager = IocManager.Instance.IocContainer.Resolve<IAccessTokenManager>();
if (tokenManager.IsRefreshTokenExpired)
{
await HandleSessionExpired(tokenManager);
}
else
{
response = await RefreshAccessTokenAndSendRequestAgain(request, cancellationToken, tokenManager);
}
return response;
}
Есть мысли по этому поводу?