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环境部署失败分析贴(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行错误:Application Err
- 下一篇: 2018年第九届蓝桥杯 第五题:快速排序