尝试将 HTTP 重定向到 HTTPS(C#、IIS),但 HTTPS 在响应标头中转回 HTTP - 重定向循环

Posted

技术标签:

【中文标题】尝试将 HTTP 重定向到 HTTPS(C#、IIS),但 HTTPS 在响应标头中转回 HTTP - 重定向循环【英文标题】:Trying to redirect HTTP to HTTPS (C#, IIS), but HTTPS turns back to HTTP in response headers - redirect loop 【发布时间】:2016-05-29 10:21:53 【问题描述】:

我在同一个 IIS 服务器上设置了两个 IIS 网站。网站 A 包含大部分内容,这是用户在请求我们的地址时显示的内容(例如 www.websitea.com)。网站 B 是一个单独的项目,仅包含整个内容的一部分,因此它是内部的(在 IIS 中绑定到 websiteb.com),但通过 URL 重写,用户可以通过键入 www.websitea.com/websiteb 来访问它.

网址重写在网站 A 的 web.config 中如下所示:

<rewrite>
  <rules>
    <clear />
    <rule name="Website B rewrite rule" stopProcessing="true">
      <match url="^websiteb(.*)" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="CACHE_URL" pattern="^(https?)://" />
      </conditions>
      <action type="Rewrite" url="C:1://websiteb.comR:1" />
    </rule>
  </rules>
</rewrite>

CACHE_URL 和 C:1 位用于保持使用的协议。例如。在 HTTP 上请求 www.websitea.com/websiteb/foo.html 的用户在 HTTP 上被“重写”为 websiteb.com/foo.html,在 HTTPS 上对 websitea.com/websiteb/bar.html 的请求被“重写”通过 HTTPS 访问 websiteb.com/bar.html。

现在,对于某些网站 B 页面,我们希望用户仅使用 HTTPS - 这是在 SomePageViewModel 的 ShouldBeHttps 属性中设置的。所以在 ActionFilterAttribute 中使用了以下代码:

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    
        if (filterContext.HttpContext.Request.IsSecureConnection)
            return;

        var result = filterContext.Result as ViewResult;
        if (result != null)
        
            if ((result.Model as SomePageViewModel).ShouldBeHttps)
            
                HandleNonHttpsRequest(filterContext);
            
        
    

    protected virtual void HandleNonHttpsRequest(ActionExecutedContext filterContext)
    
        if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException("The method must be a GET");
        string url = filterContext.HttpContext.Request.Url.ToString().Replace("http:", "https:");
        filterContext.Result = new RedirectResult(url);
    

假设 www.websitea.com/websiteb/securepage.html 将在 ShouldBeHttps 属性中产生一个真值。

现在,当我通过 HTTP 访问 websiteb.com/securepage.html 直接在服务器上对其进行测试时,我被正确重定向(状态代码 302)到 HTTPS 上的 websiteb.com/securepage.html。

我希望当我通过 HTTP 访问 www.websitea.com/websiteb/securepage.html 时,我将被重定向到通过 HTTPS 访问的 www.websitea.com/websiteb/securepage.html。但是,我的浏览器最终进入重定向循环 (ERR_TOO_MANY_REDIRECTS)。我可以在 Fiddler 的 TextView 选项卡中看到它似乎设置正确:

<html>
 <head>
  <title>Object moved</title>
 </head>
 <body>
 <h2>Object moved to <a href="https://www.websitea.com/websiteb/securepage.html">here</a>.</h2>
 </body>
</html>

但标题选项卡显示:

Response Headers
HTTP/1.1 302 Found
(...)
Transport
  Location: http://www.websitea.com/websiteb/securepage.html

所以不是去 https,而是再次 http 并再次点击过滤器,依此类推。

我有什么遗漏吗?是 IIS 设置吗?

【问题讨论】:

我认为问题在于重写规则看不到传入的 http 或 https 调用之间的区别,因此它将两者都重写回 https。 我相信它工作正常,我可以看到对 HTTPS www.websitea.com/websiteb/index.html 的请求正确地转到 HTTPS websiteb.com/index.html 和 HTTP 到 HTTP; HttpContext.Current.Request 上的 IsSecureConnection 属性正确设置为 true/false。 啊。我知道了。我误读了那部分。但是如果你想让websitea在rewrite规则中重定向到websiteb,那么不应该是吗?跨度> 不。这位于 websitea 的 web.config 中, 粗略地转换为 " 用于此 websitea 在其 url 路径(即 websitea.com 之后的位)接收到的请求/) 以 websiteb" 开头,然后 以 "return the markup serviced by websiteb.com" 结束句子。不过,可能还缺少其他东西 :( 感谢您的尝试! 【参考方案1】:

这主要是 IIS 中的一个错误

1.禁用URL重写缓存

2.在规则中添加“不安全”变量

3.清除缓存

最好的方法是,如果你可以在不使用重写的情况下在代码中做到这一点

根据您使用的 IIS 版本,这可以修复您的错误:

x64

x86

KB2974666

【讨论】:

【参考方案2】:

试试这个配置。适用于我的网站

<rule name="Redirect to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions><add input="HTTPS" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://HTTP_HOST/R:1" redirectType="SeeOther" />
</rule>

【讨论】:

不,不,我需要使用那个 ShouldBeHttps 值,只有在重写完成后才会在服务器端“计算”;所以我不能在重写操作中“硬编码”https。

以上是关于尝试将 HTTP 重定向到 HTTPS(C#、IIS),但 HTTPS 在响应标头中转回 HTTP - 重定向循环的主要内容,如果未能解决你的问题,请参考以下文章

asp.net c#从http重定向到https

使用 htaccess 将 Https 重定向到 http

API 网关将 http 重定向到 https

如何将所有 HTTP 请求重定向到 HTTPS

HTTP 重定向到不同端口中的 HTTPS

MVC 永久使用重定向 HTTP 到 HTTPS 并关闭开发环境的方法