我正在测试新的负载均衡分段站点,https是在负载均衡器级别设置的,而不是在站点级别。此外,此网站将始终为https,因此我不需要远程需要https属性等。网址显示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;
}
这个基本网址相同,协议是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文件和谷歌字体。我在这里使用//没有http或https,但这些被视为http,我在FireBug中看到混合内容被阻止的消息。
我如何克服这个问题?
答案 0 :(得分:13)
正如您所说,HTTPS终止是在负载均衡器级别完成的(“https是在负载均衡器级别设置的”),这意味着原始方案可能不会来到站点,具体取决于loadbalancer配置
看起来在你的情况下,LB被配置为始终通过HTTP与站点通信。因此,您的网站永远不会在HttpContext.Request.RawUrl
(或类似属性)上看到原始方案。
修复:通常当LB,代理或CDN以这种方式配置时,会有额外的标头指定原始方案以及可能的其他传入请求参数,例如完整网址,客户端的IP,这些代理设备后面的网站将无法直接看到。< / p>
答案 1 :(得分:1)
根据https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer
通过HTTP代理HTTPS请求时,原始方案(HTTPS) 可能会丢失,必须在标题中转发。
在Asp.Net Core中,我发现(不确定它是否适用于所有场景)即使request.Scheme误导性地显示原始“https”的“http”,request.IsHttps属性也更可靠。 我使用以下代码
//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;
}
答案 2 :(得分:1)
我重写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>
答案 3 :(得分:0)
我知道这是一个老问题,但在遇到同样的问题之后,我确实发现如果我查看HttpRequest
对象的UrlReferrer属性,这些值将反映实际的内容客户端浏览器的地址栏。
例如,我得到了UrlReferrer
:
Request.UrlReferrer.Scheme == "https"
Request.UrlReferrer.Port == 443
但对于相同的请求,使用Url
属性我得到以下内容:
Request.Url.Scheme == "http"
Request.Url.Port == 80