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.cs和TokenClient.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"));
}
}
    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);
}
}
}

IdentityServer4源码颁发token分析及性能优化的更多相关文章

  1. IdentityServer4源码解析_1_项目结构

    目录 IdentityServer4源码解析_1_项目结构 IdentityServer4源码解析_2_元数据接口 IdentityServer4源码解析_3_认证接口 IdentityServer4 ...

  2. identityserver4源码解析_2_元数据接口

    目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...

  3. IdentityServer4源码解析_4_令牌发放接口

    目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...

  4. HTTP请求库——axios源码阅读与分析

    概述 在前端开发过程中,我们经常会遇到需要发送异步请求的情况.而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率. axios是一个在近些年来非常火的 ...

  5. 如何实现一个HTTP请求库——axios源码阅读与分析 JavaScript

    概述 在前端开发过程中,我们经常会遇到需要发送异步请求的情况.而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率. axios是一个在近些年来非常火的 ...

  6. identityserver4源码解析_3_认证接口

    目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...

  7. IdentityServer4源码解析_5_查询用户信息接口

    协议简析 UserInfo接口是OAuth2.0中规定的需要认证访问的接口,可以返回认证用户的声明信息.请求UserInfo接口需要使用通行令牌.响应报文通常是json数据格式,包含了一组claim键 ...

  8. 从源码的角度分析ViewGruop的事件分发

    从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View ...

  9. 安卓图表引擎AChartEngine(二) - 示例源码概述和分析

    首先看一下示例中类之间的关系: 1. ChartDemo这个类是整个应用程序的入口,运行之后的效果显示一个list. 2. IDemoChart接口,这个接口定义了三个方法, getName()返回值 ...

随机推荐

  1. Android自动化之Monkey测试(二)

    本文主要从以下方面进行分享. 一.查看应用包名二.Monkey启动三.Monkey停止四.Monkey命令五.日志分析 一.查看应用包名 大多数时候,我们都是对特定的应用进行monkey测试,因此需要 ...

  2. OO第二单元单元总结

    总述 OO的第二单元主题是电梯调度,与第一单元注重对数据的输入输出的处理.性能的优化不同,第二单元的重心更多的是在线程安全与线程通信上.这此次单元实验之前,我并未对线程有过了解,更谈不上“使用经验”, ...

  3. xtrabackup命令用法实战(转)

    xtrabackup命令用法实战 转载出自 https://blog.csdn.net/wfs1994/article/details/80399408 完全备份 1.创建备份 [root@linux ...

  4. STL之vector容器详解

    vector 容器 vector是C++标准模版库(STL,Standard Template Library)中的部分内容.之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说: ...

  5. PowerShell工作流学习-6-向脚本工作流添加检查点

    关键点: a)检查点是工作流当前状态的快照,其中包括变量的当前值以及在该点生成的任何输出,这些信息保存在磁盘. b)检查点数据保存在托管工作流会话的计算机的硬盘上的用户配置文件中. c)当工作流通用参 ...

  6. usb2.0、usb3.0、usb3.1、type-c 接口含义与区别

    简单说: usb3.0 比2.0的传输速率快,充电快,能向下兼容2.0 usb3.1 通常是指 usb3.1 gen2,比3.0的传输速率更快.充电更快,同兼容 type-c 通常是指 usb3.1的 ...

  7. pyspider爬取tourism management 所有文章的标题 作者 摘要 关键词等等所有你想要的信息

    #!/usr/bin/env python # -*- encoding: utf-8 -*- # vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8: # C ...

  8. Excel列A、B、C、D----与列序号的转换

    public static class ExcelConvert { public static int ToExcelIndex(this string columnName) { if (!Reg ...

  9. MySQL下创建数据库以及授权用户

    一.新建数据库 1.首先登录MySQL:(输入 mysql -u root -p 命令,然后输入密码按回车即可) 2.在mysql> 下输入如下命令,回车,即可创建数据库 (test为数据库名) ...

  10. day16_雷神_前端04

    前端day04 链接前端的一些库,一些资源,从bootcdn上搜,有前端所有的库. 前端工作流程: jquery的DOM文档操作 <!DOCTYPE html> <html lang ...