【问题标题】:MVC3 Redirect LoopMVC3 重定向循环
【发布时间】:2013-07-10 09:36:55
【问题描述】:

我已经为这个问题寻找解决方案超过 10 个小时,但没有任何答案。在我的应用程序中,我使用 [requirehttps] 属性。单击带有此属性的操作方法时,我在 IE 中得到“无法显示网页”。深入研究该问题后,我发现我在 Fiddler 中收到了无限的 302 调用,这最终会超时并导致该错误。所以我决定创建一个自定义属性并物理创建 https 调用。我正在使用 IIS Express 并成功创建了证书并绑定了端口。如果我直接通过浏览器调用此 URL,一切正常。这是我一直用来重定向的代码请求。

public class HttpsAttribute : System.Web.Mvc.RequireHttpsAttribute
{
public bool RequireSecure = false;

public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext){
  var builder = new UriBuilder(HttpContext.Current.Request.Url);

  if (RequireSecure){
    // redirect to HTTP version of page         
    builder.Scheme = Uri.UriSchemeHttps;
    builder.Port = 44300;
    filterContext.Result = new RedirectResult(builder.Uri.ToString());
  }       
  else{         
    // non secure requested         
    if (filterContext.HttpContext.Request.IsSecureConnection){             
      HandleNonHttpRequest(filterContext);         
    }       
  }    
}    

protected virtual void HandleNonHttpRequest(AuthorizationContext filterContext){      
  if (String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)){         
    // redirect to HTTP version of page         
    string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;         
    filterContext.Result = new RedirectResult(url);      
  }   
}
}

当我设置断点以找出构建器值是什么时,它是正确的。正是从这里我收到了一个无限重定向循环。奇怪的是,当我在浏览器中查看 URL 时,第一个请求永远不会正确。就好像 UriBuilder 没有发送正确的 URL。有任何想法吗?这让我发疯了。

【问题讨论】:

  • 无限重定向循环是什么意思?

标签: asp.net-mvc iis https


【解决方案1】:

发生重定向循环是因为代码只检查是否需要 HTTPS 重定向,而不是当前请求是否已经是 HTTPS(即重定向已经发生)。

if (RequireSecure && !filterContext.HttpContext.Request.IsSecureConnection){
  // redirect to HTTP version of page         
  builder.Scheme = Uri.UriSchemeHttps;
  builder.Port = 44300;
  filterContext.Result = new RedirectResult(builder.Uri.ToString());
}       
else{         
  // non secure requested         
  if (filterContext.HttpContext.Request.IsSecureConnection){             
    HandleNonHttpRequest(filterContext);         
  }       
} 

尽管RequireHttps 应该可以正常工作,除非您需要重定向到指定的端口。

编辑: 重构属性

public class HttpsAttribute : System.Web.Mvc.RequireHttpsAttribute
{
    public bool RequireSecure = false;

    public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
    {
        var requestUri = HttpContext.Current.Request.Url;
        var requestIsSecure = HttpContext.Current.Request.IsSecureConnection;

        if (RequireSecure && !requestIsSecure)
            filterContext.Result = Redirect(requestUri, Uri.UriSchemeHttps, 44300);
        else if (!RequireSecure && requestIsSecure)
            filterContext.Result = Redirect(requestUri, Uri.UriSchemeHttp, 80);

    }

    private RedirectResult Redirect(Uri uri, string scheme, int port)
    {
        return new RedirectResult(new UriBuilder(uri) { Scheme = scheme, Port = port }.Uri.ToString());
    }
}

【讨论】:

  • 布伦特感谢您的回复。在我创建这个自定义属性之前,我使用的是 RequiredHttps 并且仍然接收到一个重定向循环。当 IE 提示我“此网站的安全证书有问题”并单击继续时,浏览器中的 URL 仍然是 http。单击继续后,无限重定向循环开始。我添加了您提到的附加条件检查,它确实修复了重定向循环,但现在返回 http 而不是 https。
  • @Aaron 我能够重新创建问题,我最初的答案需要更多重构,我已经编辑了答案。
  • 感谢工作的芽。真的很感激。仍然不确定为什么RequiredHttps 让我沿着这条路走下去。我将不得不回过头来找出发生了什么。
猜你喜欢
  • 1970-01-01
  • 2017-02-11
  • 2013-07-28
  • 2015-03-21
  • 2017-05-17
  • 2015-08-31
  • 2014-01-05
  • 2013-05-18
  • 1970-01-01
相关资源
最近更新 更多