• IdentityServer4源码颁发token分析及性能优化


    IdentityServer4源码地址

    IdentityModel源码地址

    1. 以下的流程用ResourceOwnerPassword类型获取token作为介绍
    2. 分两种获取形式说明
      1. token请求地址为默认TokenEndPoint的地址:"http://demo/connect/token"获取token
      2. 用IdentityModel的TokenClient请求获取token【 性能优化点也在这个地方】

    1.默认TokenEndPoint形式 


    2.TokenClient形式

    当请求的Token的地址没有配置默认形式的时候,那就需要利用IdentityModel下的Client来进行请求 举个例子

    首先我们需要去获取当前系统的token终结点(tokenEndPoint),然后获取到TokenClient,然后调用RequestResourceOwnerPasswordAsync进行Token颁发

    using (var client = new DiscoveryClient(IssuerUri) { Policy = { RequireHttps = false } })

    {

        res = await client.GetAsync();

    }

    var tokenClient = new TokenClient(res.TokenEndpoint, clientId, clientSecret);

    var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password);

    然后我们来看看实际在干什么。我们去看这部分IdentiyModel的源码 (TokenClientExtensions.csTokenClient.cs

    图1的方法就是我们调用时的方法,可以看到它构造了一下form表单元素就去调用RequestAsync方法。RequestAsync 是使用了HttpClient发起了请求。请求的地址是我们前面获取到的tokenEndPoint的地址,

    其实就是进行了一次跳转,问题点就在于这里,绕了一个"圈圈",压测出来效果并不好,为什么不选择直接本地调用方法形式去执行呢? 只需要 仿照 重写一个TokenClient和TokenEndPoint(一直感觉这东西

    既然是执handler为什么不叫TokenEndPointHandler) 去把执行方法重写掉,去掉HTTP请求方式,换成直接本地调用方式。这样就直接到类似说明S2步骤

        public class LocalTokenClient : TokenClient
        {
            private readonly ILocalTokenEndpointHandler _endpointHandler;
            public LocalTokenClient(string address, string clientId, string clientSecret, ILocalTokenEndpointHandler endpointHandler, HttpMessageHandler innerHttpMessageHandler = null, AuthenticationStyle style = AuthenticationStyle.BasicAuthentication) : base(address, clientId, clientSecret, innerHttpMessageHandler, style)
            {
                _endpointHandler = endpointHandler;
            }
    
            public override async Task<TokenResponse> RequestAsync(IDictionary<string, string> form, CancellationToken cancellationToken = default(CancellationToken))
            {
                form.Add("client_id", ClientId);
                form.Add("client_secret", ClientSecret);
    
                try
                {
                    var endpointResult = await _endpointHandler.ProcessAsync(form);
                    if(endpointResult is TokenResult)
                    {
                        TokenResult response = (TokenResult)endpointResult;
                        if (response != null && response.Response != null)
                        {
                            Dictionary<string, object> result = new Dictionary<string, object>();
                            result.Add("id_token", response.Response.IdentityToken);
                            result.Add("access_token", response.Response.AccessToken);
                            result.Add("refresh_token", response.Response.RefreshToken);
                            result.Add("expires_in", response.Response.AccessTokenLifetime);
                            result.Add("token_type", OidcConstants.TokenResponse.BearerTokenType);
    
                            if (!response.Response.Custom.IsNullOrEmpty())
                            {
                                foreach (var item in response.Response.Custom)
                                {
                                    result.Add(item.Key, item.Value);
                                }
                            }
    
                            return new TokenResponse(Newtonsoft.Json.JsonConvert.SerializeObject(result));
                        }
                    }
                    else
                    {
                        TokenErrorResult response = (TokenErrorResult)endpointResult;
                        string error = response.Response.Error;
                        if(response.Response.ErrorDescription!=null)
                        {
                           error = response.Response.ErrorDescription;
                        }
                        return new TokenResponse(new Exception(error));
                    }
                }
                catch (Exception ex)
                {
                    return new TokenResponse(ex);
                }
    
                return new TokenResponse(new Exception("request token failed"));
            }
        }
    View Code
        public interface ILocalTokenEndpointHandler
        {
            /// <summary>
            /// Processes the request.
            /// </summary>
            /// <param name="context">The HTTP context.</param>
            /// <returns></returns>
            Task<IEndpointResult> ProcessAsync(IDictionary<string, string> form);
        }
    
        public class LocalTokenEndpoint : ILocalTokenEndpointHandler
        {
            private readonly ICustomClientSecretValidator _clientValidator;
            private readonly ITokenRequestValidator _requestValidator;
            private readonly ITokenResponseGenerator _responseGenerator;
            private readonly IEventService _events;
            private readonly ILogger _logger;
            private readonly IClientStore _clients;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="TokenEndpoint" /> class.
            /// </summary>
            /// <param name="clientValidator">The client validator.</param>
            /// <param name="requestValidator">The request validator.</param>
            /// <param name="responseGenerator">The response generator.</param>
            /// <param name="events">The events.</param>
            /// <param name="logger">The logger.</param>
            public LocalTokenEndpoint(
                ICustomClientSecretValidator clientValidator,
                ITokenRequestValidator requestValidator,
                ITokenResponseGenerator responseGenerator,
                IEventService events,
                ILogger<LocalTokenEndpoint> logger,
                IClientStore clients)
            {
                _clientValidator = clientValidator;
                _requestValidator = requestValidator;
                _responseGenerator = responseGenerator;
                _events = events;
                _logger = logger;
                _clients = clients;
            }
    
            /// <summary>
            /// Processes the request.
            /// </summary>
            /// <param name="context">The HTTP context.</param>
            /// <returns></returns>
            public async Task<IEndpointResult> ProcessAsync(IDictionary<string, string> form)
            {
                _logger.LogTrace("Processing token request.");
    
                return await ProcessTokenRequestAsync(form);
            }
    
            private Task RaiseSuccessEventAsync(string clientId, string authMethod)
            {
                return _events.RaiseAsync(new ClientAuthenticationSuccessEvent(clientId, authMethod));
            }
    
            private async Task<IEndpointResult> ProcessTokenRequestAsync(IDictionary<string, string> form)
            {
                _logger.LogDebug("Start token request.");
                // validate client
                var clientResult = await _clientValidator.ValidateAsync(form);
                if (clientResult.Client == null)
                {
                    return Error(OidcConstants.TokenErrors.InvalidClient);
                }
    
                // validate request
                var form2 = form.AsNameValueCollection();
                _logger.LogTrace("Calling into token request validator: {type}", _requestValidator.GetType().FullName);
                var requestResult = await _requestValidator.ValidateRequestAsync(form2, clientResult);
    
                if (requestResult.IsError)
                {
                    await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult));
                    return Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse);
                }
    
                // create response
                _logger.LogTrace("Calling into token request response generator: {type}", _responseGenerator.GetType().FullName);
                var response = await _responseGenerator.ProcessAsync(requestResult);
    
                await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));
                LogTokens(response, requestResult);
    
                // return result
                _logger.LogDebug("Token request success.");
                return new TokenResult(response);
            }
    
            private TokenErrorResult Error(string error, string errorDescription = null, Dictionary<string, object> custom = null)
            {
                var response = new TokenErrorResponse
                {
                    Error = error,
                    ErrorDescription = errorDescription,
                    Custom = custom
                };
    
                return new TokenErrorResult(response);
            }
    
            private void LogTokens(TokenResponse response, TokenRequestValidationResult requestResult)
            {
                var clientId = $"{requestResult.ValidatedRequest.Client.ClientId} ({requestResult.ValidatedRequest.Client?.ClientName ?? "no name set"})";
                var subjectId = requestResult.ValidatedRequest.Subject?.GetSubjectId() ?? "no subject";
    
                if (response.IdentityToken != null)
                {
                    _logger.LogTrace("Identity token issued for {clientId} / {subjectId}: {token}", clientId, subjectId, response.IdentityToken);
                }
                if (response.RefreshToken != null)
                {
                    _logger.LogTrace("Refresh token issued for {clientId} / {subjectId}: {token}", clientId, subjectId, response.RefreshToken);
                }
                if (response.AccessToken != null)
                {
                    _logger.LogTrace("Access token issued for {clientId} / {subjectId}: {token}", clientId, subjectId, response.AccessToken);
                }
            }
        }
    View Code
  • 相关阅读:
    几款国产的安卓系统
    微软所有正版软件下载网站ITELLYOU
    微软所有正版软件下载网站ITELLYOU
    键盘大小写状态显示(Softswitch) v2.3汉化绿色版
    牛顿定律的一些思考
    查看接地有没有ok
    Adobe Audition CC 2018软件安装
    声音的掩蔽效应的一些思考
    声学测量的基本量
    The Mean of the Sample Mean|Standard Deviation of the Sample Mean|SE
  • 原文地址:https://www.cnblogs.com/TeemoHQ/p/9568465.html
Copyright © 2020-2023  润新知