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. BaseDao.util(虎大将军)

    package logistics.util; import java.sql.Connection; import java.sql.PreparedStatement; import java.s ...

  2. short s=1;s=s+1;short s=1;s+=1;有什么区别?

    short s = 1; s = s + 1; 这个编译一定是不通过的,会提示损失精度. short s = 1; s += 1: 这个编译反而可以通过. 隐式类型转换可以由小到大自动转,即byte ...

  3. 能量模型与softmax和RBM以及正态分布的关联

    上面一篇文章中探讨了玻尔兹曼分布的起源: 在不清楚目标的真实分布,也不知道样本分布的时候,假设任意输入与输出组合都是同样可能发生的,这样是最公平,最无偏的先验. 因为无法直接统计出给定任意一种输入x, ...

  4. ajax 参数记录

    1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如 ...

  5. python 基础———— 字符串常用的调用 (图2)

    1.  replace 2.  join 3.split 4 rsplit 5. strip : 去除字符串左右两边特定(指定)的字符 7. rstrip  :  去除右边特定(指定)的字符 8. l ...

  6. 第八周助教工作总结——NWNU李泓毅

    1.助教博客链接: https://www.cnblogs.com/NWNU-LHY/ 2.作业要求博客链接: http://www.cnblogs.com/nwnu-daizh/p/10687492 ...

  7. JavaScript中的Undefined / Null 类型相关说明

    1,综述: ※Undefined 和 Null是JavaScript中的两种数据类型(其他的类型还有:Boolean, String, Number, Object). ※Undefined类型只有一 ...

  8. Linux 云计算运维之路

    搭建中小型网站的架构图 s1-2 Linux 硬件基础 s3-4 linux 基础 文件系统 用户权限 s5-6 Linux 标准输出 系统优化 目录结构 w7 rsync-备份服务器 w8 NFS服 ...

  9. mysql官方的测试数据库employees超30万的数据,安装方法介绍

    安装方法 1.mysql必须开启环境变量 2.shift右键官方数据库打开在命令行运行此窗口 3.进入cmd以后输入mysql -uroot -proot 回车 4.输入 source  employ ...

  10. [转]构建高性能MySQL体系

    来源:http://www.yunweipai.com/archives/21232.html 构建高性能MySQL系统涵盖从单机.硬件.OS.文件系统.内存到MySQL 本身的配置,以及schema ...