C# ASP.NET Core 2.1在应用程序引擎中没有HTTP/HTTPS重定向 问题

C# ASP.NET Core 2.1在应用程序引擎中没有HTTP/HTTPS重定向 问题,c#,asp.net,google-app-engine,asp.net-core,google-cloud-platform,C#,Asp.net,Google App Engine,Asp.net Core,Google Cloud Platform,当应用程序发布到应用程序引擎时,我无法使从HTTP到HTTPS的自动重定向正常工作 EXPOSE 443 EXPOSE 8080 当我通过example.com访问该网站时,该网站被路由到并显示连接不安全。 当我通过该网站访问该网站时,谷歌管理的SSL将正确保护该网站。但是,不会发生从HTTP到HTTPS的自动重定向 我在日志查看器中还收到一个错误,警告Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware无法确定重定向的htt

当应用程序发布到应用程序引擎时,我无法使从HTTP到HTTPS的自动重定向正常工作

EXPOSE 443
EXPOSE 8080
当我通过example.com访问该网站时,该网站被路由到并显示连接不安全。 当我通过该网站访问该网站时,谷歌管理的SSL将正确保护该网站。但是,不会发生从HTTP到HTTPS的自动重定向

我在日志查看器中还收到一个错误,警告Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware无法确定重定向的https端口

我遵循了MSDN的文档,只在本地运行,但在应用程序发布到AppEngine时不运行。

这是Program.cs。基本上是项目模板的默认值

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    return WebHost.CreateDefaultBuilder(args)
        .CaptureStartupErrors(true)
        .UseStartup<Startup>();
}
我尝试了以下方法(一次只能尝试一种)
  • 将HttpSreDirection中间件添加到ConfigureServices方法 最终导致应用程序无法访问(502服务器错误)

  • 将环境变量添加到app.yaml
  • 也导致应用程序无法访问(502服务器错误)

  • 在Program.cs中手动配置HTTPS端口
  • 也导致应用程序无法访问(502服务器错误)

  • 在ConfigureServices方法中配置ForwardedHeaderOptions,并在Configure方法中使用ForwardedHeaderOptions 应用程序可访问,但没有自动HTTP/HTTPS重定向

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

    不知何故,我在创建了自己的中间件之后实现了这一点,该中间件根据本文和文档中的提示查找“X-Forwarded-Proto”头

    Microsoft:必须启用转发头中间件,应用程序才能使用UseForwardedHeaders处理转发头

    应用程序引擎:SSL连接在负载平衡器处终止。来自负载平衡器的流量通过加密通道发送到实例,然后通过HTTP转发到应用程序服务器。X-Forwarded-Proto头允许您了解原始请求是HTTP还是HTTPs

    Microsoft要求在应用程序开始处理转发的头文件之前首先激活中间件

    因此,在ConfigureServices方法中配置中间件选项

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = 
            ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });
    
    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);
        }
    });
    
    然后编写自定义中间件,读取转发的头并重定向到HTTPS(包括查询)

    中配置方法

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = 
            ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });
    
    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();
    }
    

    现在导航到直接重定向我

    可以在
    启动中手动设置方案。在使用任何类型的中间件之前配置

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

    这就是我的工作原理(代码位于Startup.cs中):

    public void配置服务(IServiceCollection服务)
    {
    配置(选项=>
    {
    options.ForwardedHeaders=
    ForwardedHeaders.XForwardedFor|
    ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
    });
    services.AddHttpsRedirection(opt=>opt.HttpsPort=443);
    //为清晰起见,代码已删除
    }
    public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
    {
    if(env.IsDevelopment())
    {
    //为清晰起见,代码已删除
    }
    其他的
    {
    //为清晰起见,代码已删除
    app.UseHsts();
    }
    app.UseForwardedHeaders();
    app.UseHttpsRedirection();
    //为清晰起见,代码已删除
    }
    
    这是一个很好的答案,对我很有用。我想补充一点,您应该使用
    context.Response.Redirect(https,true)
    而不是
    context.Response.Redirect(https)
    ,因为前者将使用HTTP状态代码301而不是302进行重定向。谷歌建议使用301来达到这个目的:非常感谢你!我一直在为此奋斗。仍然有点恼火,听起来这里的说明应该涵盖这个用例,而不需要定制重定向。
    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);
        }
    });
    
    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();
    }
    
    app.Use((context, next) =>
    {
        context.Request.Scheme = "https";
        return next();
    });
    
    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
    }