Asp.net-Core

向 .NET Core 3 應用程序添加身份伺服器身份驗證失敗,並顯示“未指定密鑰類型”。

  • April 13, 2020

我正在嘗試將身份伺服器身份驗證添加到 .NET Core 3 API 項目。

我已經添加了這段程式碼

public void ConfigureServices(IServiceCollection services)
{
   … 

   var identityBuilder = services.AddIdentityServer();

   identityBuilder.AddApiAuthorization<ApplicationUser, DbContext>();

   services
       .AddAuthentication()
       .AddIdentityServerJwt();

   var fileName = Path.Combine("Certificates", "certificatefile.pfx");
   var cert = new X509Certificate2(fileName, "veryDifficultPassword");
   identityBuilder.AddSigningCredential(cert);

   … 
}

和:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   … 
   app.UseAuthentication();
   app.UseIdentityServer(); // <--- this line throws error.
   app.UseAuthorization();
   … 
}

文件夾中有一個被正確讀取和載入的/Certificates文件——我可以檢查cert變數,它看起來是正確的。

到目前為止,我所做的一切都以這條線結束app.UseIdentityServer();

System.InvalidOperationException:“未指定密鑰類型。”

有什麼建議?

更新:包括堆棧跟踪

System.InvalidOperationException
 HResult=0x80131509
 Message=Key type not specified.
 Source=Microsoft.AspNetCore.ApiAuthorization.IdentityServer
 StackTrace:
  at Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials.LoadKey()
  at Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials.Configure(ApiAuthorizationOptions options)
  at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
  at Microsoft.Extensions.Options.OptionsManager`1.<>c__DisplayClass5_0.<Get>b__0()
  at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
  at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
  at System.Lazy`1.CreateValue()
  at System.Lazy`1.get_Value()
  at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
  at Microsoft.Extensions.Options.OptionsManager`1.Get(String name)
  at Microsoft.Extensions.Options.OptionsManager`1.get_Value()
  at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.<AddClients>b__7_1(IServiceProvider sp)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
  at Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.TestService(IServiceProvider serviceProvider, Type service, ILogger logger, String message, Boolean doThrow)
  at Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.Validate(IApplicationBuilder app)
  at Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.UseIdentityServer(IApplicationBuilder app, IdentityServerMiddlewareOptions options)
  at Boskapstorget.API.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in C:\Private\Kod\Boskapstorget\Backend\src\Boskapstorget.API\Startup.cs:line 86
  at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
  at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
  at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
  at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass13_0.<UseStartup>b__2(IApplicationBuilder app)
  at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
  at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
  at Microsoft.AspNetCore.Hosting.GenericWebHostService.<StartAsync>d__31.MoveNext()

我不認為您為安裝簽名證書而添加的程式碼導致了問題。堆棧跟踪中的程式碼正在執行,因為identityBuilder.AddApiAuthorization<ApplicationUser, DbContext>();呼叫AddSigningCredentials()最終將程式碼配置為在 appsettings.json 中查找鍵定義Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials

public SigningCredentials LoadKey()
{
   var key = new KeyDefinition();
   _configuration.Bind(key);
   switch (key.Type)
   {
       case KeySources.Development:
           var developmentKeyPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath ?? DefaultTempKeyRelativePath);
           var createIfMissing = key.Persisted ?? true;
           _logger.LogInformation($"Loading development key at '{developmentKeyPath}'.");
           var developmentKey = new RsaSecurityKey(SigningKeysLoader.LoadDevelopment(developmentKeyPath, createIfMissing))
           {
               KeyId = "Development"
           };
           return new SigningCredentials(developmentKey, "RS256");
       case KeySources.File:
           var pfxPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath);
           var pfxPassword = key.Password;
           var storageFlags = GetStorageFlags(key);
           _logger.LogInformation($"Loading certificate file at '{pfxPath}' with storage flags '{key.StorageFlags}'.");
           return new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromFile(pfxPath, key.Password, storageFlags)), "RS256");
       case KeySources.Store:
           if (!Enum.TryParse<StoreLocation>(key.StoreLocation, out var storeLocation))
           {
               throw new InvalidOperationException($"Invalid certificate store location '{key.StoreLocation}'.");
           }
           _logger.LogInformation($"Loading certificate with subject '{key.Name}' in '{key.StoreLocation}\\{key.StoreName}'.");
           return new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromStoreCert(key.Name, key.StoreName, storeLocation, GetCurrentTime())), "RS256");
       case null:
           throw new InvalidOperationException($"Key type not specified.");
       default:
           throw new InvalidOperationException($"Invalid key type '{key.Type ?? "(null)"}'.");
   }
}

您遇到這種null情況是因為您的appsettings.jsonappsettings.Development.json文件未配置Key.

我可以通過 2 種方式重現您的問題:

註釋掉 appsetting中的關鍵配置。開發*.json*

{
 "Logging": {
   "LogLevel": {
     "Default": "Debug",
     "System": "Information",
     "Microsoft": "Information"
   }
 },
 "IdentityServer": {
   //"Key": {
   //  "Type": "Development"
   //}
 }
}

這假設您正在開發環境中執行\調試

在此處輸入圖像描述

Key第二種重現方式是配置為在生產中執行,預設情況下在appsettings.json中沒有定義

在此處輸入圖像描述

我認為解決您的問題的方法是在appsettings.jsonappsettings.Development.json中定義證書文件:

{
 "Logging": {
   "LogLevel": {
     "Default": "Debug",
     "System": "Information",
     "Microsoft": "Information"
   }
 },
 "IdentityServer": {
   "Key": {
     "Type": "File",
     "FilePath": "Certificates\\certificatefile.pfx",
     "Password": "veryDifficultPassword"
   }
 }
}

並刪除此程式碼

var fileName = Path.Combine("Certificates", "certificatefile.pfx");
var cert = new X509Certificate2(fileName, "veryDifficultPassword");
identityBuilder.AddSigningCredential(cert);

引用自:https://stackoverflow.com/questions/58135672