我正在尝试比较两个服务器变量作为 URL 重写条件的一部分。但首先,先了解一些背景信息...
在 IIS 中,如果您请求的http://www.example.com/foo
是foo
目录,IIS 会将 302“对象已移动”重定向发送http://www.example.com/foo/
至“礼貌重定向”(来源)。
如果您使用 IIS+ARR 作为具有 SSL 卸载的反向代理,则后端 IIS 节点接收的请求是通过 http 而不是 https。
结合这两种行为,IIS 的礼貌重定向会丢弃 SSL。礼貌重定向使用与 IIS 收到的请求相同的方案(来源),在这种情况下是 http 而不是 https。
我想创建一个出站重写规则,将传入的 URL 与传出的 Location 标头进行比较,并在本例中将其从 http 重写为 https:
- 响应是重定向:
{RESPONSE_STATUS}
是 302 - 传入请求通过 SSL:
{HTTPS}
处于“开启”状态 - 传入的 URL 没有以斜杠结尾。
- 传出的 Location 标头以斜线结尾。
以上所有内容都是在前提条件中处理的。棘手的部分是最后一点:
- 传出 Location 标头的路径与传入 URL 相同,但附加了斜杠。
以下是我目前的代码。前提条件和标头重写都工作正常。但是,条件会导致 500 错误(URL 重写模块错误),大概是因为我{REQUEST_URI}
在模式中使用了它。我尝试将条件分成两个并使用捕获组,但这也不起作用。有什么想法吗?
<rule name="Fix: Courtesy Redirect + SSL Offloading = SSL dropped" preCondition="Courtesy Redirect Drops SSL" enabled="true">
<match serverVariable="RESPONSE_LOCATION" pattern="^http://(.+/)$" />
<conditions>
<add input="{RESPONSE_LOCATION}" pattern="{REQUEST_URI}/" />
</conditions>
<action type="Rewrite" value="https://{R:1}" />
</rule>
<preConditions>
<preCondition name="Courtesy Redirect Drops SSL">
<add input="{RESPONSE_STATUS}" pattern="^302$" />
<add input="{HTTPS}" pattern="^on$" />
<add input="{REQUEST_URI}" pattern=".*[^/]$" />
<add input="{RESPONSE_LOCATION}" pattern="^http://.+/$" />
</preCondition>
</preConditions>
答案1
您可以使用自定义重写提供程序。提供程序是将一个字符串转换为另一个字符串的 C# 代码。然后,您可以按照与使用重写映射类似的方式使用它:
您可以选择在 URL 中完全无效的分隔符。(也许使用空格或类似的东西。我将使用它,|
以便它在这篇文章中可见,但您应该选择其他字符串。)
您将编写一条规则来设置服务器变量的值IsItMatching
。 服务器变量的值将使用您的自定义 URL 重写提供程序进行设置:
{provider_name:{server_variable_1}|{server_variable_2}}
然后,实现提供程序的 C# 代码将执行以下操作(伪代码,无错误检查):
string Rewrite(string input)
{
string[] inputVariables = input.split(separator);
if (inputVariables[0] == inputVariables[1] + "/")
return "yes";
else
return "no";
}
然后,您将再编写一条规则来检查服务器变量的值IsItMatching
是“是”还是“否”。