【问题标题】:jwt authentication in ASP.Net Core API not working with Kestrel ServerASP.Net Core API 中的 jwt 身份验证不适用于 Kestrel 服务器
【发布时间】:2022-01-24 17:14:08
【问题描述】:

我正在尝试验证我的 API JWT,但无法编译,因为它给出了错误:

- $exception {"Scheme 已存在:Bearer"} System.InvalidOperationException

如果我删除身份验证代码,那么它工作得很好。如果我将身份验证代码放在 program.cs 中,那么我可以编译,但是当我将它作为 Windows 服务托管时,我又可以编译。我收到错误 500。

program.cs

 var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddEnvironmentVariables()
            .AddJsonFile("certificate.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"certificate.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
            .Build();

            string certificateFileName = "C:\\old\\kestrelssl.pfx";
            string certificatePassword = "12345";

            var certificate = new X509Certificate2(certificateFileName, certificatePassword);

            return Host.CreateDefaultBuilder(args)
                /*.ConfigureServices(services => {
                services.AddAuthentication(option =>
                {
                    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                  .AddJwtBearer(option =>
                  {
                      option.RequireHttpsMetadata = true;         //made purposly to test ssl with kestrel
                         option.TokenValidationParameters = new TokenValidationParameters()
                      {
                          ValidateLifetime = true,
                          ValidateIssuer = true,
                          ValidateAudience = true,
                          ValidIssuer = ConfigHelper.AppSetting("issuer"),
                          ValidAudience = ConfigHelper.AppSetting("audience"),
                          IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(ConfigHelper.AppSetting("secretkey"))),
                          ClockSkew = TimeSpan.Zero
                      };
                  });
            })*/
               .ConfigureWebHost(webBuilder =>
               {
                   webBuilder.UseKestrel(options =>
                   {
                       options.AddServerHeader = false;
                       options.Listen(IPAddress.Loopback, 44302, listenOptions =>
                       {
                           listenOptions.UseHttps(certificate);
                       });
                   })
                   .UseIISIntegration()
                   .UseConfiguration(config)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .UseUrls("https://localhost:44302");
                   webBuilder.UseStartup<Startup>();
               }).UseWindowsService(); ;
        }

Startup.Cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(option =>
            {
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                 .AddJwtBearer(option =>
                 {
                     option.RequireHttpsMetadata = false;
                     option.TokenValidationParameters = new TokenValidationParameters()
                     {
                         ValidateLifetime = true,
                         ValidateIssuer = true,
                         ValidateAudience = true,
                         ValidIssuer = ConfigHelper.AppSetting("issuer"),
                         ValidAudience = ConfigHelper.AppSetting("audience"),
                         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(ConfigHelper.AppSetting("secretkey"))),
                         ClockSkew = TimeSpan.Zero
                     };
                 });
            services.AddMvc(options => { options.EnableEndpointRouting = false; });
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // Use the default property (Pascal) casing
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            });
           // services.AddHttpsRedirection(options => options.HttpsPort = 5001);
            
            services.AddScoped<IApplication, Application>();
            services.AddScoped<IServiceRepository, ServiceRepository>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseMvc();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection();

            app.UseAuthentication();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "ServiceNS/{action}");
            });
        }

堆栈跟踪

  at Microsoft.AspNetCore.Authentication.AuthenticationOptions.AddScheme(String name, Action`1 configureBuilder)
   at Microsoft.AspNetCore.Authentication.AuthenticationBuilder.<>c__DisplayClass4_0`2.<AddSchemeHelper>b__0(AuthenticationOptions o)
   at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions 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.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options, IDictionary`2 schemes)
   at Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   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.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.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.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass5_0.<UseMiddleware>b__0(RequestDelegate next)
   at Microsoft.AspNetCore.Builder.ApplicationBuilder.Build()
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.<StartAsync>d__31.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__9.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
   at ***.Program.Main(String[] args) in D:\Learning\Projects\***\Program.cs:line 20

【问题讨论】:

    标签: asp.net-core-webapi kestrel


    【解决方案1】:

    根据你的program.cs代码,我发现你调用了startup.cs两次,建议你修改一下,去掉一个startup.cs再试。

            .UseStartup<Startup>()
            .UseUrls("https://localhost:44302");
                   webBuilder.UseStartup<Startup>();
    

    感谢 Brando 对此进行了调查,我删除了其中一个 Startup Reference 并按预期工作。

    但是当我将 EXE 作为 Windows 服务启动时,它只是给了我 InternalServerError,所以我进一步查看了事件日志,发现如下:

    Exception: 
    System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Windows\system32\appsettings.json'.
    

    只要我将它 (appsettings.json) 粘贴到 C:/Windows/system32 中,它就可以正常工作了。

    过去 3 天我一直在摸不着头脑,希望这对将来的人有所帮助。

    【讨论】:

    • 真棒白兰度,它(部分)解决了我的编译问题。但是,如果我直接使用 EXE 启动它,它的工作,但是一旦我从 WIndowsServices 启动它,它就会开始给出 InternalServerError。如何从中获取更多信息?感谢您的努力。
    • 能否请您分享详细信息 500 错误?
    • 在谷歌浏览器上它给出了这个错误消息:这个页面不工作 localhost 当前无法处理这个请求。 HTTP 错误 500
    • 看起来我解决了这个问题,在事件日志中显示,System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional。物理路径是“C:\Windows\system32\appsettings.json”。我刚刚复制并粘贴到 system32 中,现在它可以工作了
    猜你喜欢
    • 2020-07-26
    • 2018-01-28
    • 1970-01-01
    • 2019-09-06
    • 2021-04-20
    • 2017-03-02
    • 2019-09-03
    • 1970-01-01
    • 2019-05-19
    相关资源
    最近更新 更多