У меня есть приложение asp.net core с React front-end, которое использует IdentityServer. Оно было создано с помощью шаблонов scaffold в Visual Studio 2019. Приложение отлично работает локально, но при развертывании на AWS beanstalk происходит сбой. Строка кода, на которой происходит сбой, находится в методе Configure моего Startup.cs. app.UseIdentityServer().

Где-то в UseIdentityServer() есть исключение нулевой ссылки, которое я не вижу и не могу воспроизвести при локальном тестировании на моей машине разработки.

Вот мой метод Configure() в Startup.cs:

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 beanstalk, выглядит следующим образом:

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)

Has anybody run into this before? This is something that is specific to deploying to в AWS Beanstalk. Если я удалю вызов UseIdentityServer(), приложение публикуется и работает нормально в AWS Beanstalk. Я публикуюсь на Linux beanstalk, если это имеет значение. Должно быть, что-то должно быть настроено по-другому в IdentityServer при развертывании на Linux, или, возможно, что-то специфическое в 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, должно работать нормально, если я выберу "Build self contained deployment bundle" при публикации через AWS Toolkit for Visual Studio.

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

Ответы (1)

Разница между моим локальным хостом и AWS Beanstalk, которая вызывала ошибку на Beanstalk, заключалась в прокси-сервере Nginx. Мне пришлось учесть это, добавив следующее промежуточное ПО в метод ConfigureServices() моего Startup.cs.

services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders =
                ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        });

Это объясняется следующим:

Когда HTTPS-запросы передаются через HTTP, оригинальная схема (HTTPS) теряется и должна быть передана в заголовке.

Поскольку приложение получает запрос от прокси-сервера, а не от истинного источника в Интернете или корпоративной сети, IP-адрес клиента, отправляющего запрос, также должен быть передан в заголовке.

Более подробная информация приведена в следующей статье:https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0

2022 WebDevInsider