Проблема с устаревшим доступом - PullRequest
0 голосов
/ 21 января 2020

Мы используем нулевую базовую версию шаблона с приложением форм 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;
        }

Есть мысли по этому поводу?

...