如何在使用 Windows.Web.Http 的 UWP 应用中使用为 System.Net.Http 添加的 IdentityModel 扩展方法 (TokenRefresh)

问题描述

我想在使用 Windows.Web.Http 的 UWP 应用中使用为 System.Net.Http 添加的 IdentityModel 扩展方法 (TokenRefresh)。但是,我目前使用的是 4.3.1 版。 在此版本上,Windows.Web.Http.HttpClient 扩展不可用。

Nuget: Install-Package IdentityModel -Version 4.3.1

解决方法

IdentityModel refused to add supportWindows.Web.Http 模块的创建者。所以我自己实现了刷新令牌。欢迎您在此处指出任何问题。

public static async Task<HttpClient> GetHttpClient()
    {
        var httpBaseProtocolFilter = new HttpBaseProtocolFilter
        {
            MaxVersion = HttpVersion.Http20,};
        return await SetHeaders(new HttpClient(httpBaseProtocolFilter));
    }

private static async Task<HttpClient> SetHeaders(HttpClient httpClient)
    {
        try
        {
            httpClient.DefaultRequestHeaders.Add("X-requestIp",DeviceIp);
            httpClient.DefaultRequestHeaders.Add("client","5");

            if (OAuth2Manager.Token != null && !string.IsNullOrWhiteSpace(OAuth2Manager.Token.AccessToken))
                httpClient.DefaultRequestHeaders.Add("Authorization",string.Format("Bearer {0}",OAuth2Manager.Token.AccessToken));

            return httpClient;
        }
        catch (Exception)
        {
            throw;
        }
    }

private static async Task<ResponseDataModel> RequestSender1(object postData,string requestUrl,string requestMehtod,Action<HttpProgress> OnSendRequestProgress)
        {
            try
            {
                HttpClient httpClient = await GetHttpClient();
                httpClient = await SetBearerToken(httpClient);

                //Do all the request send related stuff here
            }
            catch (Exception)
            {

            }
        }

static readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1,1);
private static async Task<HttpClient> SetBearerToken(HttpClient httpClient)
    {
        try
        {
            if (OAuth2Manager.TokenExpiration < DateTime.Now)
            {
                await semaphoreSlim.WaitAsync();
                try
                {
                    await OAuth2Manager.RequestRefreshTokenAsync();
                }
                finally
                {
                    semaphoreSlim.Release();
                }
            }

            return httpClient;
        }
        catch (Exception)
        {
            throw;
        }
    }

//retryCount = 3
    //tempRetryCount = 1
    public static async Task<TokenResponse> RequestRefreshTokenAsync()
    {
        try
        {
            do
            {
                if (retryCount == tempRetryCount) break;

                Token = await RequestRefreshTokenAsyncInternal();
                tempRetryCount++;

                if (Token.IsError || !string.IsNullOrWhiteSpace(Token.Error))
                {
                    //Log errors
                }

            } while (Token.IsError || !string.IsNullOrWhiteSpace(Token.Error));


            if (Token.IsError || !string.IsNullOrWhiteSpace(Token.Error))
            {
                //Log errors
                return Token;
            }

            //percentage == 80
            //Token expiration set as 80% of the actual expire value so 20% of the remaining time can be
            //used to send a refresh token request.
            TokenExpiration = DateTime.Now.AddSeconds(Token.ExpiresIn * percentage / 100);
            return Token;
        }
        catch (Exception)
        {
            throw;
        }
    }

private static async Task<TokenResponse> RequestRefreshTokenAsyncInternal()
    {
        try
        {
            if (Token == null || Token.RefreshToken != null)
            {
                Token = await httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest()
                {
                    Address = discoveryDocumentResponse.TokenEndpoint,RefreshToken = Token.RefreshToken,ClientId = clientId,ClientSecret = clientSecret,AuthorizationHeaderStyle = BasicAuthenticationHeaderStyle.Rfc6749,});

                if (Token.IsError && Token.HttpStatusCode == System.Net.HttpStatusCode.BadRequest && Token.Error.Equals(ApplicationConstants.InvalidGrant))
                {
                    await RequestPasswordTokenAsync(Global.Username,Global.Password);
                }
            }
            else
            {
                await RequestPasswordTokenAsync(Global.Username,Global.Password);
            }

            if (Token.IsError || !string.IsNullOrWhiteSpace(Token.Error))
            {
                //Log errors
            }

            return Token;
        }
        catch (Exception)
        {
            throw;
        }
    }

希望你能理解我所做的。干杯!