示例#1
0
        /// <summary>
        /// RefreshAccessTokenAsync
        /// </summary>
        /// <param name="apiClient"></param>
        /// <param name="endpointSettings"></param>
        /// <returns></returns>
        /// <exception cref="ApiException"></exception>
        public static async Task <bool> RefreshAccessTokenAsync(IApiClient apiClient, EndpointSettings?endpointSettings)
        {
            if (UserPreferences.AccessToken.IsNullOrEmpty())
            {
                return(false);
            }

            JwtEndpointSetting jwtEndpoint = endpointSettings == null?apiClient.GetDefaultJwtEndpointSetting() : endpointSettings.JwtEndpoint;

            string accessTokenHashKey = SecurityUtil.GetHash(UserPreferences.AccessToken);

            //这个AccessToken不久前刷新过
            if (!_requestLimiter.NoWaitLock(nameof(RefreshAccessTokenAsync), accessTokenHashKey, TimeSpan.FromSeconds(jwtEndpoint.RefreshIntervalSeconds)))
            {
                //可能已经有人在刷新,等他刷新完
                if (!await _lastRefreshResultsAccessSemaphore.WaitAsync(TimeSpan.FromSeconds(10)).ConfigureAwait(false))
                {
                    //等待失败
                    BaseApplication.ExceptionHandler(ApiExceptions.TokenRefreshError(cause: "AccessToken 有人刷新过,等待获取结果失败。"));
                    return(false);
                }

                try
                {
                    if (_lastRefreshResults.TryGetValue(accessTokenHashKey, out bool lastRefreshResult))
                    {
                        return(lastRefreshResult);
                    }

                    BaseApplication.ExceptionHandler(ApiExceptions.TokenRefreshError(cause: "AccessToken 有人刷新过,但结果获取为空。"));
                    return(false);
                }
                finally
                {
                    _lastRefreshResultsAccessSemaphore.Release();
                }
            }

            //开始刷新,其他想取结果的人等着
            await _lastRefreshResultsAccessSemaphore.WaitAsync().ConfigureAwait(false);

            try
            {
                if (UserPreferences.RefreshToken.IsNotNullOrEmpty())
                {
                    RefreshAccessTokenRequest refreshRequest = new RefreshAccessTokenRequest(
                        jwtEndpoint.EndpointName !,
                        jwtEndpoint.Version !,
                        HttpMethod.Get,
                        jwtEndpoint.ResourceName !,
                        UserPreferences.AccessToken,
                        UserPreferences.RefreshToken);

                    AccessTokenResource?resource = await apiClient.GetFirstOrDefaultAsync(refreshRequest).ConfigureAwait(false);

                    if (resource != null)
                    {
                        _lastRefreshResults.Clear();
                        _lastRefreshResults[accessTokenHashKey] = true;

                        OnRefreshSucceed(resource);

                        return(true);
                    }
                }

                //刷新失败
                _lastRefreshResults.Clear();
                _lastRefreshResults[accessTokenHashKey] = false;

                OnRefreshFailed();

                return(false);
            }
            catch
            {
                //刷新失败
                _lastRefreshResults.Clear();
                _lastRefreshResults[accessTokenHashKey] = false;

                OnRefreshFailed();

                throw;
            }
            finally
            {
                _lastRefreshResultsAccessSemaphore.Release();
            }
        }