博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IdentityServer4源码颁发token分析及性能优化
阅读量:4354 次
发布时间:2019-06-07

本文共 8164 字,大约阅读时间需要 27 分钟。

  1. 以下的流程用ResourceOwnerPassword类型获取token作为介绍
  2. 分两种获取形式说明
    1. token请求地址为默认TokenEndPoint的地址:""获取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
RequestAsync(IDictionary
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
result = new Dictionary
(); 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    {        ///         /// Processes the request.        ///         /// The HTTP context.        /// 
Task
ProcessAsync(IDictionary
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; ///
/// Initializes a new instance of the
class. ///
///
The client validator. ///
The request validator. ///
The response generator. ///
The events. ///
The logger. public LocalTokenEndpoint( ICustomClientSecretValidator clientValidator, ITokenRequestValidator requestValidator, ITokenResponseGenerator responseGenerator, IEventService events, ILogger
logger, IClientStore clients) { _clientValidator = clientValidator; _requestValidator = requestValidator; _responseGenerator = responseGenerator; _events = events; _logger = logger; _clients = clients; } ///
/// Processes the request. /// ///
The HTTP context. ///
public async Task
ProcessAsync(IDictionary
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
ProcessTokenRequestAsync(IDictionary
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
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

 

转载于:https://www.cnblogs.com/TeemoHQ/p/9568465.html

你可能感兴趣的文章
单工、半双工和全双工的定义
查看>>
Hdu【线段树】基础题.cpp
查看>>
时钟系统
查看>>
BiTree
查看>>
5个基于HTML5的加载动画推荐
查看>>
水平权限漏洞的修复方案
查看>>
静态链接与动态链接的区别
查看>>
如何使用mysql
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第11节 Logback日志框架介绍和SpringBoot整合实战_45、SpringBoot2.x日志讲解和Logback配置实战...
查看>>
类中的静态函数和非静态函数的区别
查看>>
windows 下安装Apache
查看>>
Fedora14 mount出现错误时解决办法【亲测有效】
查看>>
使用Visual Studio 2013进行UI自动化测试
查看>>
13-集体照
查看>>
读了曾国藩家书,,心态逐渐平和起来。搞技术的如果缺乏信念的指引,生活会很乏味无聊!...
查看>>
160809308周子济第六次作业
查看>>
大型Web应用运行时 PHP负载均衡指南
查看>>
为phpStorm 配置PHP_CodeSniffer自动检查代码
查看>>
测试工具网址大全(转)
查看>>
ServiceStack DotNet Core前期准备
查看>>