尝试将 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,那么这主要是 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 - 重定向循环的主要内容,如果未能解决你的问题,请参考以下文章