request.url.scheme在负载平衡站点上提供HTTP而不是HTTP



我正在测试一个新的负载均衡登台站点,而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-ForX-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;
    }

最新更新