将 asp.net Core REACT 应用程序部署到 AWS Beanstalk 时 IdentityServer 出错

Error with IdentityServer when deploying asp.net Core REACT app to AWS Beanstalk

我有一个 asp.net 核心应用程序,其 React 前端使用 IdentityServer。它是在 Visual Studio 2019 年使用脚手架模板创建的。该应用程序在本地运行良好,但在我部署到 AWS beanstalk 时失败。它失败的代码行在我的 Startup.csConfigure 方法中。 app.UseIdentityServer().

UseIdentityServer() 的某处有一个我看不到的空引用异常,在我的开发机器上进行本地测试时我无法重现。

这是我在 Startup.cs 中的 Configure() 方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            //app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        //app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseIdentityServer();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                //spa.UseReactDevelopmentServer(npmScript: "start"); // Starts CRA automatically
                spa.UseProxyToSpaDevelopmentServer("http://localhost:3000"); // Must manually start CRA (yarn start)
            }
        });
    }
}

我在检查 AWS beantalk 日志时遇到如下错误:

Jan 1 00:36:57 ip-172-30-2-135 web: #033[41m#033[30mfail#033[39m#033[22m#033[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] Jan 1 00:36:57 ip-172-30-2-135 web: An unhandled exception has occurred while executing the request. Jan 1 00:36:57 ip-172-30-2-135 web: System.NullReferenceException: Object reference not set to an instance of an object. Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.b__10_2(IServiceProvider sp) Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)

有人 运行 以前参与过这个吗?这是特定于部署到 AWS beanstalk 的东西。如果我删除 UseIdentityServer() 调用,应用程序会在 AWS Beanstalk 中发布并且 运行 正常。如果这有所不同,我将发布到 Linux beantalk。部署到 Linux 时,必须使用 IdentityServer 进行不同的配置,或者可能需要使用 AWS Beanstalk 进行特定配置。

当 运行 在我的开发机器上本地运行时,它在 Windows 10 以防有帮助。

编辑:添加 ConfigureServices() 方法

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<BarristerContext>(options =>
            options.UseNpgsql(
                Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<BarristerContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>();
        
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest)
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
                options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
            });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

            options.LoginPath = $"/Identity/Account/Login";
            options.LogoutPath = $"/Identity/Account/Logout";
            options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
        });

        // using Microsoft.AspNetCore.Identity.UI.Services;
        services.AddSingleton<IEmailSender, EmailSender>();

        services.AddIdentityServer(options => 
        {
            options.UserInteraction = new UserInteractionOptions()
            {
                LogoutUrl = "/Identity/account/logout",
                LoginUrl = "/Identity/account/login",
                LoginReturnUrlParameter = "returnUrl"
            };
        }).AddApiAuthorization<ApplicationUser, BarristerContext>();

        services.AddAuthentication().AddIdentityServerJwt();

        services.AddControllersWithViews();
        services.AddRazorPages();

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });

        //services.AddDatabaseDeveloperPageExceptionFilter();
    }

我还要注意,我在此部署上的目标是 .Net 5,根据 AWS,只要我在通过 AWS 发布时 select“构建自包含部署包”,它应该可以正常工作Visual Studio.

的工具包

https://aws.amazon.com/blogs/developer/aws-elastic-beanstalk-adds-net-core-on-linux-platform/

我的本地主机与导致 Beanstalk 错误的 AWS Beanstalk 之间的区别是 Nginx 代理。我必须通过在 Startup.cs.

的 ConfigureServices() 方法中添加以下中间件来解决这个问题
services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders =
                ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        });

这是由于:

当通过 HTTP 代理 HTTPS 请求时,原始方案 (HTTPS) 丢失,必须在 header 中转发。

因为应用从代理接收请求而不是它在 Internet 或公司网络上的真实来源,所以原始客户端 IP 地址也必须在 header 中转发。

以下文章提供了更多详细信息:https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0