IdentityServer4环境部署失败分析贴(一)
前言:
在部署Idv4站点和其客户端在外网时,发现了许多问题,折腾了许久,翻看了许多代码,写个MD记录一下。
1.受保护站点提示错误: Unable to obtain configuration from: '[PII is hidden]'.
fail: Microsoft.AspNetCore.Server.Kestrel[13]Connection id "0HLL3MB34N0G5", Request id "0HLL3MB34N0G5:00000009": An unhandled exception was thrown by the application.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden]'.在 Microsoft.IdentityModel.Protocols.ConfigurationManager`1.<GetConfigurationAsync>d__24.MoveNext()
--- 引发异常的上一位置中堆栈跟踪的末尾 ---在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)在 Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.<HandleChallengeAsync>d__18.MoveNext()
--- 引发异常的上一位置中堆栈跟踪的末尾 ---在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)在 Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<ChallengeAsync>d__54.MoveNext()
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
1.1 受保护站点的代码执行流程
graph TB
User--1.进入-->A(Home/Index)
A--2.Authorize-->AA{是否授权}
AA--YES-->完事
AA--NO-->B(返回ChallengeResult)
B--3.ExecuteResult-->C(进入AuthenticationMiddleware中间件)
C--4.根据authenticationScheme找到相应Handler-->D(OpenIDConenctHandler)
D--5.调用HandleChallengeAsync-->F(调用OpenIdConnectConfigurationRetriever.IConfigurationRetriever)
F--6.通过HTTP调用Idv4站点的/.well-known/openid-configuration-->F1(Idv4Config)
F1--7.通过上步骤取到的config.jwks_uri获取加密key信息-->F2(获得公钥私钥等信息)
F2--8.设置JsonWebKeySet-->F3(完成openIdConnectConfiguration.SigningKeysKeys的添加)
F3-->F4(完成)
1.1 受保护站点的部分源码
Idv4部分源码
//注入Idev相关,配置authenticationScheme为oidc
public static IIdentityServerBuilder AddIdentityServer(this IServiceCollection services, Action<IdentityServerOptions> setupAction)
{services.Configure(setupAction);return services.AddIdentityServer();
}
PS: 这里要额外提一下,在Abp的模板项目中,如下配置使用Idv4可能无法正常跳转IDV4授权站完成单点登录
services.AddOpenIdConnect("oidc", options =>
{...
}
需要额外添加下面这段,原因是Abp引入Microsoft.Identity,会重复设置schme导致错误,需如下代码添加设置。
services.AddAuthentication(options =>
{options.DefaultAuthenticateScheme = "oidc";options.DefaultChallengeScheme = "oidc";options.DefaultSignOutScheme = "oidc";
})
步骤5部分源码
protected override async Task HandleChallengeAsync(AuthenticationProperties properties){Logger.EnteringOpenIdAuthenticationHandlerHandleUnauthorizedAsync(GetType().FullName);// order for local RedirectUri// 1. challenge.Properties.RedirectUri// 2. CurrentUri if RedirectUri is not set)if (string.IsNullOrEmpty(properties.RedirectUri)){properties.RedirectUri = CurrentUri;}Logger.PostAuthenticationLocalRedirect(properties.RedirectUri);if (_configuration == null && Options.ConfigurationManager != null){//问题在这里_configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);}...
步骤6部分源码
public static async Task<OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel){if (string.IsNullOrWhiteSpace(address))throw LogHelper.LogArgumentNullException(nameof(address));if (retriever == null){throw LogHelper.LogArgumentNullException(nameof(retriever));}//当站点没启动的时候,这里可能出现问题string doc = await retriever.GetDocumentAsync(address, cancel).ConfigureAwait(false);LogHelper.LogVerbose(LogMessages.IDX21811, doc);OpenIdConnectConfiguration openIdConnectConfiguration = JsonConvert.DeserializeObject<OpenIdConnectConfiguration>(doc);if (!string.IsNullOrEmpty(openIdConnectConfiguration.JwksUri)){LogHelper.LogVerbose(LogMessages.IDX21812, openIdConnectConfiguration.JwksUri);//当证书配置或读取错误的时候,这里会出现问题string keys = await retriever.GetDocumentAsync(openIdConnectConfiguration.JwksUri, cancel).ConfigureAwait(false);LogHelper.LogVerbose(LogMessages.IDX21813, openIdConnectConfiguration.JwksUri);openIdConnectConfiguration.JsonWebKeySet = JsonConvert.DeserializeObject<JsonWebKeySet>(keys);foreach (SecurityKey key in openIdConnectConfiguration.JsonWebKeySet.GetSigningKeys()){openIdConnectConfiguration.SigningKeys.Add(key);}}return openIdConnectConfiguration;}
通过流程进行问题解析:
通过查看日志可发现在流程5后开始报错
步骤一
访问:http://{ssoHost}/.well-known/openid-configuration
如果访问成功,则排除单点登录站点部署失败问题,前往步骤二
如果访问失败,则去解决单点登录站点部署问题。
步骤二
http://{ssoHost}/.well-known/openid-configuration/jwks
如果访问成功,则重启客户端
如果访问失败,那么有意思了...继续往下看
###### 此时单点登录站点的日志
[10:25:24 Error] Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware
An unhandled exception has occurred while executing the request.
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: 出现了内部错误。at Internal.Cryptography.Helpers.OpenStorageProvider(CngProvider provider)at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, String curveName, CngKeyBlobFormat format, CngProvider provider)at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat format)at Internal.Cryptography.Pal.X509Pal.DecodePublicKey(Oid oid, Byte[] encodedKeyValue, Byte[] encodedParameters, ICertificatePal certificatePal)at System.Security.Cryptography.X509Certificates.PublicKey.get_Key()at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PublicKey()at IdentityServer4.ResponseHandling.DiscoveryResponseGenerator.CreateJwkDocumentAsync()at IdentityServer4.Endpoints.DiscoveryKeyEndpoint.ProcessAsync(HttpContext context)at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
##### 单点登录站点在此时的工作流程
graph TBA(通过Http获取发现服务的配置信息)--1.进入SSO站点-->B(IdentityServerMiddleware)
B--2.调用Process-->C(进入DiscoveryKeyEndpoint)
C--3.遍历注入的加密Key-->D(返回JsonBWebKey)
部分源码解析:
public async Task Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events){// this will check the authentication session and from it emit the check session// cookie needed from JS-based signout clients.await session.EnsureSessionIdCookieAsync();try{//根据请求路径,进入相应endpoint处理器var endpoint = router.Find(context);if (endpoint != null){_logger.LogInformation("Invoking IdentityServer endpoint: {endpointType} for {url}", endpoint.GetType().FullName, context.Request.Path.ToString());var result = await endpoint.ProcessAsync(context);...
//创建JwtDocumentpublic virtual async Task<IEnumerable<Models.JsonWebKey>> CreateJwkDocumentAsync(){var webKeys = new List<Models.JsonWebKey>();var signingCredentials = await Keys.GetSigningCredentialsAsync();var algorithm = signingCredentials?.Algorithm ?? Constants.SigningAlgorithms.RSA_SHA_256;foreach (var key in await Keys.GetValidationKeysAsync()){if (key is X509SecurityKey x509Key){var cert64 = Convert.ToBase64String(x509Key.Certificate.RawData);var thumbprint = Base64Url.Encode(x509Key.Certificate.GetCertHash());//当证书读取不正常的时候,PublicKey的属性构造器中会报错。var pubKey = x509Key.PublicKey as RSA;var parameters = pubKey.ExportParameters(false);var exponent = Base64Url.Encode(parameters.Exponent);var modulus = Base64Url.Encode(parameters.Modulus);var webKey = new Models.JsonWebKey{kty = "RSA",use = "sig",kid = x509Key.KeyId,x5t = thumbprint,e = exponent,n = modulus,x5c = new[] { cert64 },alg = algorithm};webKeys.Add(webKey);continue;}
问题解析
通过日志可发现,问题出现在PublicKey的获取上,即证书的读取失败了。
解决方案!
终于到解决问题的时候了...
步骤一:
检查证书是否是临时证书
//在正式环境中,这可能会报错
builder.AddDeveloperSigningCredential(true, "tempkey.rsa");//正确方式
builder.AddSigningCredential(new X509Certificate2(path,Configuration["Certificates:Password"]))
这里可以参见郭的随笔:
https://www.cnblogs.com/guolianyu/p/9872661.html
步骤二:
如果已经添加了证书,且证书路径正确读取,且证书密码正确;
但是!在Windows Server2008服务器上部署仍失败时,请检查 CNG Key Isolation 服务是否启动!
如果 该服务未启动,则启动后即可!
如果该服务已启动,则尴尬的很...如果您仍排除不了问题,可以评论告诉我
转载于:https://www.cnblogs.com/Imaigne/p/10519493.html
IdentityServer4环境部署失败分析贴(一)相关推荐
- ELK实时日志分析平台环境部署--完整记录
在日常运维工作中,对于系统和业务日志的处理尤为重要.今天,在这里分享一下自己部署的ELK(+Redis)-开源实时日志分析平台的记录过程(仅依据本人的实际操作为例说明,如有误述,敬请指出)~ ==== ...
- vTPM架构分析与环境部署
(文章来源:vTPM架构分析与环境部署 - Linux系统教程 http://www.linuxdiyf.com/linux/22731.html) 概述 可信平台模块(Trusted Platfor ...
- kafka 基础知识梳理及集群环境部署记录
一.kafka基础介绍 Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特 ...
- MySQL高可用方案-PXC环境部署记录
之前梳理了Mysql+Keepalived双主热备高可用操作记录,对于mysql高可用方案,经常用到的的主要有下面三种: 一.基于主从复制的高可用方案:双节点主从 + keepalived 一般来说, ...
- Linux下开源邮件系统Postfix+Extmail+Extman环境部署记录
一.基础知识梳理 MUA (Mail User Agent) MUA 既是"邮件使用者代理人",因为除非你可以直接利用类似 telnet 之类的软件登入邮件主机来主动发出信件,否 ...
- 【流媒体服务器Mediasoup】环境部署与demo搭建(二)
目录 前言 服务器环境 NodeJs的安装 下载Demo源码 配置服务端 部署及测试 可能会遇到的问题 前言 上篇文章对MediaSoup进行简单的介绍 [MediaSoup]多人音视频架构.流媒体 ...
- SpringBoot与ElasticSearch、ActiveMQ、RocketMQ的整合及多环境配置、响应式框架WebFlux、服务器端主动推送SSE技术、生产环境部署、Actuator监控平台
1.SpringBoot 与 ElasticSearch 框架的整合 (1)主要的搜索框架:MySQL.Solr.ElasticSearch MySQL:使用 like 进行模糊查询,存在性能问题 S ...
- Day133.尚品汇:项目介绍、Linux软件环境部署、项目环境搭建、表设计
目录 一.电商项目介绍 二.Linux 软件环境部署 三.项目环境搭建 1.Maven 回顾 2.ElasticSearch 四.关于表设计 首页分类表 一.电商项目介绍 我们为什么要讲电商? 1. ...
- windows驱动数字签名之WHQL完整流程 | WHQL认证环境部署以及HLK测试
文章目录 第一部分:windows驱动数字签名之WHQL完整流程 一.驱动数字签名背景 二.驱动程序数字签名解决方案-WHQL认证 1. 对开发者的影响 2. WHQL认证主要作用 三.申请WHQL认 ...
最新文章
- 使用属性position:fixed的时候如何才能让div居中
- mysql大表迁移_MySQL 大表迁移
- Android 屏幕自动旋转-Sensor属性
- Solr配置IK分词器
- BZOJ 3195: [Jxoi2012]奇怪的道路 | 状压DP
- linux删除空行 基本操作
- 22行代码AC_试题 历届试题 油漆面积【解题报告】
- GDB下查看内存命令(x命令)
- [ BZOJ 4668 ] 冷战
- 允许使用抽象类类型 isearchboxinfo 的对象_此对象非彼对象(面向对象)3
- okhttp配置缓存策略_一网打尽OkHttp中的缓存问题
- 57.Linux/Unix 系统编程手册(下) -- SOCKET : Unix domain
- 理解createTrackbar函数
- MySQL数据库企业级应用实践(主从复制)
- 优矿 pandas plt 显示平安银行基金月最大召回率
- 计算机系统的图像编码方式,彩色图像编码方案
- 智能BI,如今走到了哪一步?
- pe重装系统后F盘无法打开系统拒绝访问解决方案
- 车贷需要注意的问题,车贷风控流程这几点你必须知道
- labview编程笔记之条件结构