我有一个在我的本地环境中正确运行HTTPS的网站。当我将其上传到AWS时,它只会超时或重定向。
我在AWS中的设置是一个Elastic Beanstalk应用程序,一个运行MS SQL的RDS数据库,我添加了一个Load Balancer来转发HTTPS请求,我有一个正确分配给Load Balancer的SSL证书。从我可以告诉我的应用程序正在运行,事实上,实体框架已启动并在我的RDS实例中正确构建了我的数据库。我无法通过互联网访问该网站。
我尝试过以不同的方式设置听众。如果我这样设置它们,它只是永远重定向:
我有default HTTP/HTTPS port forwarding code in my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Sets all calls to require HTTPS: https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Force all HTTP requests to redirect to HTTPS: https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl
var options = new RewriteOptions().AddRedirectToHttps();
app.UseRewriter(options);
...
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto
});
...
}
我花了好几天时间才开始工作。我已经尝试取出所有的HTTPS代码,但这不起作用。我尝试过像this和this这样的博客的代码解决方案,但这也无效。根据我的阅读,Load Balancer最终处理HTTPS请求,然后将HTTP请求转发给我的应用程序。但我不知道如何正确处理,仍然强制执行HTTPS,并将HTTP重定向到HTTPS。
这似乎是没有一堆设置就可以开箱即用的东西。如果不是,我认为现在很多其他人都会遇到这个问题,并且在互联网上会有关于它的信息。我错过了一些小事吗?因为我完全在我的智慧结束。
如果你能回答这个问题,那么你将成为我的新英雄。
所以我终于解决了这个问题。首先,必须将Load Balancer设置为将HTTPS 443转发到HTTP 80,如下所示:
然后,我在问题中概述的所有代码都需要删除(或者不在AWS环境中运行)。我忘了最初删除services.Configure<MvcOptions>(options){}
代码行,我相信这是造成错误的原因。
然后我跟着this blog来处理X-Forwarded-Proto标题。我把所有代码放在一个扩展文件中:
public static class RedirectToProxiedHttpsExtensions
{
public static RewriteOptions AddRedirectToProxiedHttps(this RewriteOptions options)
{
options.Rules.Add(new RedirectToProxiedHttpsRule());
return options;
}
}
public class RedirectToProxiedHttpsRule : IRule
{
public virtual void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// #1) Did this request start off as HTTP?
string reqProtocol;
if (request.Headers.ContainsKey("X-Forwarded-Proto"))
{
reqProtocol = request.Headers["X-Forwarded-Proto"][0];
}
else
{
reqProtocol = (request.IsHttps ? "https" : "http");
}
// #2) If so, redirect to HTTPS equivalent
if (reqProtocol != "https")
{
var newUrl = new StringBuilder()
.Append("https://").Append(request.Host)
.Append(request.PathBase).Append(request.Path)
.Append(request.QueryString);
context.HttpContext.Response.Redirect(newUrl.ToString(), true);
}
}
}
最后,我在Startup.cs中调用此代码:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
var options = new RewriteOptions()
.AddRedirectToProxiedHttps()
.AddRedirect("(.*)/$", "$1"); // remove trailing slash
app.UseRewriter(options);
...
}
毕竟它终于奏效了!
根据this AWS docs你必须分析X-Forwarded-Proto
标题和重定向响应只有当它是http
(而不是https
)。
来自RedirectToHttpsRule
包的当前Microsoft.AspNetCore.Rewrite
做not analyze this。你需要实现自己的IRule
。
app.UseForwardedHeaders()似乎与AWS Load Balancers有问题,除非您先清除已知的网络和代理。
不要忘记先安装Microsoft.AspNetCore.HttpOverrides NuGet包,否则它将无声地失败。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseForwardedHeaders(GetForwardedHeadersOptions());
...
}
private static ForwardedHeadersOptions GetForwardedHeadersOptions()
{
ForwardedHeadersOptions forwardedHeadersOptions = new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
return forwardedHeadersOptions;
}
你需要接受X Forwarded Proto
在Startup.cs中:
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseForwardedHeaders();
...
}