【问题标题】:Rewrite URLs on an HTTPS page to HTTP将 HTTPS 页面上的 URL 重写为 HTTP
【发布时间】:2012-02-28 05:49:12
【问题描述】:
使用 IIS7 的“绑定”功能,我在网站的根目录中将 SSL 证书添加到“https”(端口 443)。然后,我需要一个特定目录的 SSL 连接,“/secure-directory/”。我现在可以通过显式链接到 https 地址来重定向到这个目录:https://www.mysite.com/secure-directory/。问题是 /secure-directory/ 是我想要使用 SSL 的唯一目录,它包含现在维护 https 前缀的导航链接,所以我的“主页”链接现在指向 https://www.mysite.com 而不是 http://www.mysite.com。
为 /secure-directory/ 中的链接保留 http 前缀的理想方法是什么?我有 IIS7 URL 重写模块,所以如果有人可以共享出站规则,那将不胜感激。否则,我想知道我是否以完全错误的方式解决这个问题,或者有比重写规则更好的解决方案。谢谢。
【问题讨论】:
标签:
c#
asp.net
https
url-rewriting
iis-7.5
【解决方案1】:
我正在使用this module。您可以将 /secure-directory/ 配置为只能通过 https 访问
<secureWebPages>
<directories>
<add path="secure-directory" />
</directories>
</secureWebPages>
【解决方案2】:
我通常使用这样的东西,它一直对我有用。 (虽然不完全确定这是最好的方法)。
你可以在global.asax中有这样的函数,并且可以在Application_BeginRequest
中调用
private void RedirectToCorrectSSLScheme()
{
Uri pageRequest = Request.Url;
string requestPath = pageRequest.GetLeftPart(UriPartial.Path).ToLower();
requestPath = Server.UrlDecode(requestPath);
// PageIsSecure returns if the given page should be secure or not. I
//maintain a list of secure pages or
//secure directory in an XML config.
bool securePage = GetSecurePages().PageIsSecure(requestPath);
if (pageRequest.Scheme == "https" && !securePage && requestPath.Contains(".aspx"))
{
Response.Redirect("http://" + pageRequest.Host + pageRequest.PathAndQuery, true);
}
else if (pageRequest.Scheme == "http" && securePage && requestPath.Contains(".aspx"))
{
Response.Redirect("https://" + pageRequest.Host + pageRequest.PathAndQuery, true);
}
}
【解决方案3】:
这不是 URL 重写问题,IMO。但是,至少在理论上(POC 时间?),您可以编写另一个重写规则,将其翻转回非 SSL。然而,重写方案的可扩展性不高,因为它每次人翻转时都会强制两次命中。这可能是也可能不是问题,具体取决于应用程序的正常使用情况。
处理此问题的一种简单方法是覆盖菜单控件,以便您尊重配置。这意味着菜单对其他实现使用绝对链接(非 SSL 时绝对链接,反之亦然)。
如果您需要更多“工业实力”,请考虑将 HTTP 处理程序添加到“管道”并在那里控制 SSL 或非 SSL。我会彻底了解这一点,这样您就不会最终重新发明轮子(不是这里发明的综合症),并尝试使其成为可重用的抽象。这有点复杂,但当您转向另一个解决方案时,最终会更容易重复。我会先看看是否有人开源了这样的处理程序,因为这不是一个罕见的问题。
我相信还有其他方法可以查看此问题。
【解决方案4】:
感谢您的回复。我考虑实施 global.asax 和模块解决方案,但最终最适合我需要的是出站重写规则。我可能会在以后重新审视它并重新评估我的情况,但现在,这就是我正在使用的(为了生产而删除了 1860 端口):
<rule name="ForceHttpsToHttp" preCondition="ResponseIsHtml1">
<match filterByTags="A, Img" pattern="^(?!.*javascript).*$" />
<conditions>
<add input="{HTTPS}" pattern="ON" />
<add input="{SERVER_PORT}" pattern="443" />
</conditions>
<action type="Rewrite" value="http://{HTTP_HOST}:1860{R:0}" />
</rule>
(该模式防止重写服务器端点击事件,而 (.*) 会重写并破坏它们)