首页 > 解决方案 > 如何在使用 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

标签: c#uwphttpclientwindows-10-universalidentitymodel

解决方案


IdentityModel 的创建者拒绝添加对该Windows.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;
        }
    }

希望你能明白我做了什么。干杯!


推荐阅读