簡體   English   中英

遠程要求HTTPS MVC 5

[英]Remote Require HTTPS MVC 5

我具有以下屬性,以確保遠程站點頁面以https模式打開。

public class RemoteRequireHttpsAttribute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentException("Filter Context");
            }

            if (filterContext != null && filterContext.HttpContext != null)
            {
                if (filterContext.HttpContext.Request.IsLocal)
                {
                    return;
                }
                else
                {
                    string val = ConfigurationManager.AppSettings["RequireSSL"].Trim();
                    bool requireSsl = bool.Parse(val);
                    if (!requireSsl)
                    {
                        return;
                    }
                }
            }

            base.OnAuthorization(filterContext);
        }
    }

本地開發現在正常工作,因為我不希望它以https模式打開。

開發人員站點以https模式打開頁面-此處沒有問題(單節點)。

我正在設置的生產(負載平衡-2個節點)站點在哪里給我以下錯誤。 請注意,開發和生產站點具有相同的設置和web.config

頁面未正確重定向

Firefox已檢測到服務器正在以永遠無法完成的方式重定向對該地址的請求。

有時可能是由於禁用或拒絕接受Cookie引起的。

開發站點網址類似於http://dev.datalab.something.org

產品站點網址類似於http://datalab.something.org

這是電話

[RemoteRequireHttps]
public ActionResult Index(string returnUrl, string error)

我在這里想念什么?

更新1:我的管理員已確認在便攜式平衡器evel上已設置SSL終端。 我已經查看了iis站點設置,但沒有看到https綁定。 我只看到http綁定。 他是否還需要設置https綁定?

更新2: @AlexeiLevenkov向我指出了正確的方向, 這篇文章有我使用的代碼,並且可以正常工作。 將代碼移動到單獨的答案中。

您的網站位於執行SSL終止的負載均衡器之后-因此,無論用戶看到什么,所有傳入您網站的流量都是HTTP。 這將導致您的代碼始終嘗試重定向到HTTPS版本,從而導致無限循環。

修復選項:

  • 通常,執行SSL終止的負載平衡器將通過自定義標頭轉發原始IP /協議。 x-forward-protox-forwarded-for是通常用於此目的的。 您可能需要與網絡管理員聯系,以查看是否使用了這些標頭或是否需要一些其他配置
  • 另外,您可以關閉SSL終止,但是它將給您的服務器增加負擔。
  • 還可以配置負載平衡器,以使用與傳入請求相同的協議與服務器通信。

如何調查此類問題:

  • 查看http調試器(如Fiddler)以查看是否在循環中獲得30倍重定向請求。 如果沒有重定向-可能是代碼錯誤。
  • 如果您看到重復的重定向,則可能意味着站點未看到實際的請求信息-可能是協議,缺少路徑cookie。
  • 要繼續調查,請查看用戶和服務器之間有哪些設備(CDN,代理,負載平衡器...)-每個設備都有很好的機會來釋放日期或轉換協議。

並不是我反對編寫漂亮的自定義屬性,是否可能在web.config中執行重定向並使用可用於web.config的轉換將以下啟用值從false更改為true進行生產部署是否有意義?

<rewrite>
  <rules>
    <rule name="SSL_ENABLED" enabled="false" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTPS}" pattern="^OFF$" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
    </rule>
  </rules>
</rewrite>

如@AlexeiLevenkov所述,將修復程序移到單獨的答案中。

public class RemoteRequireHttpsAttribute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentException("Filter Context");
            }

            if(filterContext.HttpContext != null)
            {
                if (filterContext.HttpContext.Request.IsSecureConnection)
                {
                    return;
                }

                var currentUrl = filterContext.HttpContext.Request.Url;
                if (currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
                {
                    return;
                }

                if (string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }

                if (filterContext.HttpContext.Request.IsLocal)
                {
                    return;
                }

                var val = ConfigurationManager.AppSettings["RequireSSL"].Trim();
                var requireSsl = bool.Parse(val);
                if (!requireSsl)
                {
                    return;
                }
            }

            base.OnAuthorization(filterContext);
        }
    }

我也更新了ExitHttps屬性。 這有類似的問題...

public class ExitHttpsAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentException("Filter Context");
            }

            if (filterContext.HttpContext == null)
            {
                return;
            }

            var isSecure = filterContext.HttpContext.Request.IsSecureConnection;

            var currentUrl = filterContext.HttpContext.Request.Url;
            if (!isSecure && currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
            {
                isSecure = true;
            }

            if (!isSecure && string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
            {
                isSecure = true;
            }

            if (isSecure)
            {
                //in these cases keep https
                // abort if a [RequireHttps] attribute is applied to controller or action
                if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                // abort if a [RetainHttps] attribute is applied to controller or action
                if (isSecure && filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                // abort if it's not a GET request - we don't want to be redirecting on a form post
                if (isSecure && !String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    isSecure = false;
                }
            }

            if (!isSecure)
            {
                return;
            }

            // redirect to HTTP
            var url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM