【问题标题】:MVC3, RequireHttps and custom handler result in http 310MVC3、RequireHttps 和自定义处理程序导致 http 310
【发布时间】:2012-04-12 21:05:34
【问题描述】:

我正在尝试构建一个使用 SSL 连接的 Web 应用程序。所以我做了一些研究,发现我可以使用 RequireHttpsAttribute 类来实现我所需要的。问题是当我使用它时,应用程序的执行会导致 310 错误(重定向太多)。我什至构建了一个自定义类来处理从 http 到 https 的切换。但这也会导致错误。

我的类来处理协议切换:

Public Class RequireSSLAttribute
    Inherits ActionFilterAttribute

    Public Property IsRequired() As Boolean

    Public Overrides Sub OnActionExecuting(filterContext As ActionExecutingContext)
        If Me.IsRequired AndAlso filterContext.HttpContext.Request.Url.Scheme <> "https" Then
            filterContext.HttpContext.Response.Redirect(filterContext.HttpContext.Request.Url.OriginalString.Replace("http:", "https:").Remove(filterContext.HttpContext.Request.Url.OriginalString.LastIndexOf(":") + 1), True)
            filterContext.Result = New HttpUnauthorizedResult
        End If
    End Sub

    Public Sub New()
        IsRequired = True
    End Sub
End Class

【问题讨论】:

    标签: asp.net-mvc vb.net asp.net-mvc-3 https


    【解决方案1】:

    我不知道你的主机是谁,但我刚刚在AppHarbor 上遇到了类似的问题,并在他们的knowledge base 中发现了这个问题:

    如果您使用内置的 RequireHttpsAttribute 来确保 控制器操作始终使用 HTTPS,您将遇到重定向 环形。原因是 SSL 在负载均衡器级别终止 并且 RequireHttps 无法识别它的 X-Forwarded-Proto 标头 用于指示请求是使用 HTTPS 发出的。你应该 因此为此目的使用自定义 RequireHttps 属性。

    他们还在 Github here 上提供了一个示例解决方案,为方便起见,我将其复制如下:

    using System;
    using System.Web.Mvc;
    using RequireHttpsAttributeBase = System.Web.Mvc.RequireHttpsAttribute;
    
    namespace AppHarbor.Web
    {
        [AttributeUsage(
            AttributeTargets.Class | AttributeTargets.Method,
            Inherited = true,
            AllowMultiple = false)]
        public class RequireHttpsAttribute : RequireHttpsAttributeBase
        {
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                if (filterContext == null)
                {
                    throw new ArgumentNullException("filterContext");
                }
    
                if (filterContext.HttpContext.Request.IsSecureConnection)
                {
                    return;
                }
    
                if (string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"],
                    "https",
                    StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }
    
                if (filterContext.HttpContext.Request.IsLocal)
                {
                    return;
                }
    
                HandleNonHttpsRequest(filterContext);
            }
        }
    }
    

    我不确定这是否能解决您的问题;但也许即使您没有使用 AppHarbor,根本原因对您来说也可能是相同的,在这种情况下,上述情况似乎值得一试。

    【讨论】:

    • 感谢发帖。这适用于 Amazon Elastic Beanstalk。
    • 这三个的顺序重要吗? if (filterContext.HttpContext.Request.IsSecureConnection), if (string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase)), if (filterContext.HttpContext.请求.IsLocal)。为什么我需要 if (filterContext.HttpContext.Request.IsSecureConnection) 和 if (filterContext.HttpContext.Request.IsLocal) 呢?
    【解决方案2】:

    试试改成

    If Me.IsRequired AndAlso filterContext.HttpContext.Request.Url.Scheme <> "https" Then
        secureUrl = filterContext.HttpContext.Request.Url.OriginalString.Replace("http:", "https:").Remove(filterContext.HttpContext.Request.Url.OriginalString.LastIndexOf(":") + 1)
        filterContext.Result = new RedirectResult(secureUrl)
    End If
    

    【讨论】:

    • 不幸的是它不起作用,但我不认为它是实际的重定向。但通过 https 访问时,它不应超过 If ... then 子句。
    • 它还在做无限重定向吗?你也有任何 AuthorizationFilters 吗?
    • 对于第一个控制器的登录控制器,我没有任何授权过滤器。然而,登录背后的控制器使用这些过滤器。但是至少我希望您在登录之前无法访问它。
    • 在保持 Fiddler 开启的同时运行它,看看它会被重定向到哪个 Url。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 2013-01-21
    • 2010-12-26
    相关资源
    最近更新 更多