簡體   English   中英

ASP.NET Core 2.1 在 App Engine 中沒有 HTTP/HTTPS 重定向

[英]ASP.NET Core 2.1 no HTTP/HTTPS redirection in App Engine

問題

當應用程序發布到 App Engine 時,我無法使從 HTTP 到 HTTPS 的自動重定向正常工作。

當我通過example.com訪問網站時,該網站被路由到http://www.example.com並顯示連接不安全。 當我通過https://www.example.com訪問該網站時,該網站將使用谷歌管理的 SSL 進行正確保護。 但是,不會發生從 HTTP 到 HTTPS 的自動重定向。

不安全的連接

我還在日志查看器中收到錯誤警告,提示 Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware 正在拋出無法確定用於重定向的 https 端口。

在此處輸入圖片說明

我遵循了 MSDN 中的文檔,只讓它在本地工作,而不是在應用程序發布到 App Engine 時。 https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&tabs=visual-studio

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory logger)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseStatusCodePages();
        app.UseExceptionHandler("/Error");
        app.UseHsts(); // This was added by the template
    }

    app.UseHttpsRedirection(); // This was added by the template
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseMvc();
}

這是 Program.cs。 基本上默認來自項目模板

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    return WebHost.CreateDefaultBuilder(args)
        .CaptureStartupErrors(true)
        .UseStartup<Startup>();
}

用於部署的 app.yaml

runtime: aspnetcore
env: flexible
automatic_scaling:
  min_num_instances: 1
  max_num_instances: 20
  cpu_utilization:
    target_utilization: 0.8
readiness_check:
  path: "/readinesscheck"
  check_interval_sec: 5
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
  app_start_timeout_sec: 300
liveness_check:
  path: "/livenesscheck"
  check_interval_sec: 30
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
skip_files:
  - node_modules/
  - wwwroot/src/vendor/
  - ^(.*/)?.*\.pdb$
  - ^(.*/)?.*\.log$

我試過的是以下(一次只有一個)

  1. 將HttpsRedirection 中間件添加到ConfigureServices 方法。

最終導致應用程序無法訪問(502 服務器錯誤)。

services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
    options.HttpsPort = 443;
});
  1. 將 EnvironmentVariable 添加到 app.yaml

最后還導致應用程序無法訪問(502 服務器錯誤)。

env_variables:
   ASPNETCORE_HTTPS_PORT: "443"
  1. 在 Program.cs 中手動配置 HTTPS 端口

最后還導致應用程序無法訪問(502 服務器錯誤)。

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080") // also return 502 when port is 443
  1. 在 ConfigureServices 方法中配置 ForwardedHeaderOptions 並在 Configure 方法中使用 ForwardedHeaderOptions。 https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1#other-proxy-server-and-load-balancer-scenarios

應用程序可訪問,但沒有自動 HTTP/HTTPS 重定向。

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

app.UseForwardedHeaders();
  1. 在 Dockerfile 中手動公開端口 443 和 8080。

應用程序可訪問,但沒有自動 HTTP/HTTPS 重定向。 我知道當app.yaml 中的運行時設置為aspnetcore 時 發布過程會自動生成它自己的 Dockerfile,用於將應用程序部署到 App Engine。

EXPOSE 443
EXPOSE 8080

根據MicrosoftApp Engine文檔中的提示,我創建了自己的中間件以查找“ X-Forwarded-Proto ”標頭后,不知何故我讓它工作。

Microsoft:必須為應用啟用轉發標頭中間件才能使用 UseForwardedHeaders 處理轉發標頭。

App Engine: SSL 連接在負載平衡器處終止。 來自負載均衡器的流量通過加密通道發送到實例,然后通過 HTTP 轉發到應用程序服務器。 X-Forwarded-Proto 標頭讓您了解原始請求是 HTTP 還是 HTTPs。

Microsoft 要求在應用程序開始處理轉發的標頭之前首先激活中間件

所以在ConfigureServices方法中配置中間件選項

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

並在其他任何事情之前在Configure方法中使用它

app.UseForwardedHeaders();

然后編寫自定義中間件,讀取轉發的標頭並重定向到 HTTPS,包括查詢。

配置方法中

app.Use(async (context, next) =>
{
    if (context.Request.IsHttps || context.Request.Headers["X-Forwarded-Proto"] == Uri.UriSchemeHttps)
    {
        await next();
    }
    else
    {
        string queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : string.Empty;
        var https = "https://" + context.Request.Host + context.Request.Path + queryString;
        context.Response.Redirect(https);
    }
});

最后Configure方法是這樣的

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseForwardedHeaders();
    app.Use(async (context, next) =>
    {
        if (context.Request.IsHttps || context.Request.Headers["X-Forwarded-Proto"] == Uri.UriSchemeHttps)
        {
            await next();
        }
        else
        {
            string queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : string.Empty;
            var https = "https://" + context.Request.Host + context.Request.Path + queryString;
            context.Response.Redirect(https);
        }
    });

    if (env.IsDevelopment())
    {
        // code removed for clarity
    }
    else
    {
        // code removed for clarity
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    // code removed for clarity
    app.UseMvc();
}

現在導航到example.com直接重定向我https://www.example.com

這對我有用(代碼位於 Startup.cs 中):

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = 
            ForwardedHeaders.XForwardedFor | 
            ForwardedHeaders.XForwardedProto;

        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });

    services.AddHttpsRedirection(opt => opt.HttpsPort = 443);

    // code removed for clarity
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        // code removed for clarity
    }
    else
    {
        // code removed for clarity
        app.UseHsts();
    }

    app.UseForwardedHeaders();
    app.UseHttpsRedirection();
    
    // code removed for clarity
}
        

該方案可以在使用任何類型的中間件之前在Startup.Configure手動設置:

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next();
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM