简体   繁体   English

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

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

Problem问题

I could not get the automatic redirection from HTTP to HTTPS to work correctly when the app is published to App Engine.当应用程序发布到 App Engine 时,我无法使从 HTTP 到 HTTPS 的自动重定向正常工作。

When i access the website through example.com the site got routed to http://www.example.com and show that the connection is unsecured.当我通过example.com访问网站时,该网站被路由到http://www.example.com并显示连接不安全。 When i access the website through https://www.example.com the website is then correctly secured with google-managed SSL.当我通过https://www.example.com访问该网站时,该网站将使用谷歌管理的 SSL 进行正确保护。 However the automatic redirection from HTTP to HTTPS does not occurs.但是,不会发生从 HTTP 到 HTTPS 的自动重定向。

不安全的连接

I also got an error in Log Viewer warning that Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware was throwing Failed to determine the https port for redirect.我还在日志查看器中收到错误警告,提示 Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware 正在抛出无法确定用于重定向的 https 端口。

在此处输入图片说明

I have followed the documentation from MSDN and only get it to work locally, but not when the app is published to App Engine.我遵循了 MSDN 中的文档,只让它在本地工作,而不是在应用程序发布到 App Engine 时。 https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&tabs=visual-studio 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();
}

Here is the Program.cs.这是 Program.cs。 Basically default from the project template基本上默认来自项目模板

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

The app.yaml used for the deployment用于部署的 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$

What I've tried was the following (Only one at a time)我试过的是以下(一次只有一个)

  1. AddHttpsRedirection Middleware to the ConfigureServices method.将HttpsRedirection 中间件添加到ConfigureServices 方法。

Which ended up with app being inaccessible (502 Server Error).最终导致应用程序无法访问(502 服务器错误)。

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

Also ended up with app being inaccessible (502 Server Error).最后还导致应用程序无法访问(502 服务器错误)。

env_variables:
   ASPNETCORE_HTTPS_PORT: "443"
  1. Manually configuring the HTTPS port in Program.cs在 Program.cs 中手动配置 HTTPS 端口

Also ended up with app being inaccessible (502 Server Error).最后还导致应用程序无法访问(502 服务器错误)。

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080") // also return 502 when port is 443
  1. Configure ForwardedHeaderOptions in ConfigureServices method and Use ForwardedHeaderOptions in Configure method.在 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 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

App is accessible but no automatic HTTP/HTTPS redirection.应用程序可访问,但没有自动 HTTP/HTTPS 重定向。

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

app.UseForwardedHeaders();
  1. Manually exposing port 443 and 8080 in Dockerfile.在 Dockerfile 中手动公开端口 443 和 8080。

App is accessible but no automatic HTTP/HTTPS redirection.应用程序可访问,但没有自动 HTTP/HTTPS 重定向。 I understand that when runtime in app.yaml is set to aspnetcore .我知道当app.yaml 中的运行时设置为aspnetcore 时 The publish process automatically generated it's own Dockerfile which is used to deploy the app to App Engine.发布过程会自动生成它自己的 Dockerfile,用于将应用程序部署到 App Engine。

EXPOSE 443
EXPOSE 8080

Somehow I got this to work after creating my own middleware that look for " X-Forwarded-Proto " header according to this hint on Microsoft and App Engine documentation.根据MicrosoftApp Engine文档中的提示,我创建了自己的中间件以查找“ X-Forwarded-Proto ”标头后,不知何故我让它工作。

Microsoft: Forwarded Headers Middleware must be enabled for an app to process forwarded headers with UseForwardedHeaders. Microsoft:必须为应用启用转发标头中间件才能使用 UseForwardedHeaders 处理转发标头。

App Engine: SSL connections are terminated at the load balancer. App Engine: SSL 连接在负载平衡器处终止。 Traffic from the load balancer is sent to the instance over an encrypted channel, and then forwarded to the application server over HTTP.来自负载均衡器的流量通过加密通道发送到实例,然后通过 HTTP 转发到应用程序服务器。 The X-Forwarded-Proto header lets you understand if the origin request was HTTP or HTTPs. X-Forwarded-Proto 标头让您了解原始请求是 HTTP 还是 HTTPs。

Microsoft requires the Middleware to be activated first before the app start to process the forwarded headers Microsoft 要求在应用程序开始处理转发的标头之前首先激活中间件

So configure the middleware options in ConfigureServices method所以在ConfigureServices方法中配置中间件选项

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

and use it in Configure method before anything else并在其他任何事情之前在Configure方法中使用它

app.UseForwardedHeaders();

Then writing the custom middleware that reads the forwarded headers and redirect to HTTPS including queries.然后编写自定义中间件,读取转发的标头并重定向到 HTTPS,包括查询。

In Configure method配置方法中

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);
    }
});

In the end the Configure method looks like this最后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();
}

Now navigating to example.com redirect me directly https://www.example.com现在导航到example.com直接重定向我https://www.example.com

This is what worked for me (the code is located in Startup.cs):这对我有用(代码位于 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
}
        

The scheme can be manually set in Startup.Configure before using any type of middleware:该方案可以在使用任何类型的中间件之前在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