我正在测试一个新的负载均衡登台站点,而HTTPS则在负载平衡器级别而不是站点级别设置。另外,此站点将始终是HTTPS,因此我不需要远程需要HTTPS属性等。URL显示HTTPS,但我的代码中不可用。由于这个原因,我有一些问题
request.url.scheme始终是http:
public static string GetProtocol()
{
var protocol = "http";
if (HttpContext.Current != null && HttpContext.Current.Request != null)
{
protocol = HttpContext.Current.Request.Url.Scheme;
}
return protocol;
}
与此基本URL相同的东西,协议是http
public static string GetBaseUrl()
{
var baseUrl = String.Empty;
if (HttpContext.Current == null || HttpContext.Current.Request == null || String.IsNullOrWhiteSpace(HttpRuntime.AppDomainAppPath)) return baseUrl;
var request = HttpContext.Current.Request;
var appUrl = HttpRuntime.AppDomainAppVirtualPath;
baseUrl = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, appUrl);
if (!string.IsNullOrWhiteSpace(baseUrl) && !baseUrl.EndsWith("/"))
baseUrl = String.Format("{0}/", baseUrl);
return baseUrl;
}
现在,最大的问题是引用样式表中引用的JS文件和Google字体。我在没有HTTP或HTTP的情况下使用//在这里使用,但它们被视为HTTP,我看到在Firebug中封锁了混合的内容。
如何克服这个问题?
您已经说过在LOAD BALANCER级别完成HTTPS终止(" HTTPS是在Load Balancer级别设置"),这意味着原始方案可能不会根据LoadBalancer配置来到网站。
在您的情况下,LB一直配置为一直通过HTTP与站点进行交谈。因此,您的网站将永远不会在HttpContext.Request.RawUrl
(或类似属性)上看到原始方案。
修复:通常,当LB,Proxy或CDN配置这样的方式时,还有其他标题可以指定原始方案,并可能其他传入请求参数(例如Full URL),client的IP(客户端的IP)将无法直接可见该代理设备后面的站点。<<<<<<<<<<<<<<<<
i覆盖ServerVariables
,以说服MVC确实通过HTTPS进行通信,还可以公开用户的IP地址。这是使用负载平衡器设置的X-Forwarded-For
和X-Forwarded-Proto
HTTP标头。
请注意,只有在您真的确定这些标头处于您的控制之下,否则客户可能会使用此功能,否则客户可能会注入他们喜欢的值。
public sealed class HttpOverrides : IHttpModule
{
void IHttpModule.Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
}
private void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
string forwardedFor = app.Context.Request.Headers["X-Forwarded-For"]?.Split(new char[] { ',' }).FirstOrDefault();
if (forwardedFor != null)
{
app.Context.Request.ServerVariables["REMOTE_ADDR"] = forwardedFor;
app.Context.Request.ServerVariables["REMOTE_HOST"] = forwardedFor;
}
string forwardedProto = app.Context.Request.Headers["X-Forwarded-Proto"];
if (forwardedProto == "https")
{
app.Context.Request.ServerVariables["HTTPS"] = "on";
app.Context.Request.ServerVariables["SERVER_PORT"] = "443";
app.Context.Request.ServerVariables["SERVER_PORT_SECURE"] = "1";
}
}
void IHttpModule.Dispose()
{
}
}
和Web.config
:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="HttpOverrides" type="Namespace.HttpOverrides" preCondition="integratedMode" />
</modules>
</system.webServer>
我知道这是一个旧问题,但是在遇到同样的问题之后,我确实发现,如果我查看 HttpRequest
对象的urlreferrer属性客户端浏览器的地址栏。
所以,例如,使用UrlReferrer
,我得到了:
Request.UrlReferrer.Scheme == "https"
Request.UrlReferrer.Port == 443
但是,对于同样的请求,使用Url
属性,我得到了以下内容:
Request.Url.Scheme == "http"
Request.Url.Port == 80
根据https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer
当HTTPS请求通过HTTP代理时,原始方案(HTTPS) 可能会丢失,必须在标题中转发。
在ASP.NET Core中,我发现(不确定它是否适用于所有情况),即使请求也可以误导地显示了原始" HTTPS"的" HTTP",request.ishtps属性更可靠。 我正在使用以下代码
//Scheme may return http for https
var scheme = request.Scheme;
if(request.IsHttps) scheme= scheme.EnsureEndsWith("S");
//General string extension
public static string EnsureEndsWith(this string str, string sEndValue, bool ignoreCase = true)
{
if (!str.EndsWith(sEndValue, CurrentCultureComparison(ignoreCase)))
{
str = str + sEndValue;
}
return str;
}