在 https 反向代理后的 IIS 站点,配置 IIS 重定向会导致 https 变为 http,如何让 IIS 重定向返回相对地址的 Location 头

问题

在 IIS 中配置 HTTP 重定向,destination 明明写的是相对路径:

<system.webServer>
    <httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found" destination="/test/login/#/sso$Q" />
</system.webServer>

但实际返回的 Location 响应头还是从 http:// 开始的完整地址:

Location: http://主机名/test/login/#/sso?ticket=abc123

在反向代理、内外网映射等场景下,这可能会导致 https 地址被降级为 http,进而导致地址不能访问或者还需要多一次重定向。

原因

IIS 的 HTTP 重定向模块(httpRedirect)在生成 302 响应时,会自动用当前请求的协议和 Host 头把目标补全成绝对地址,没有任何开关可以关掉。exactDestination 只控制是否把原请求路径追加到目标后面,与绝对/相对无关。

URL Rewrite 模块的入站 Redirect 动作也是同样的行为,即使 url 写相对路径,最终也会自动补全主机名(微软确认的设计行为)。

解决方案

用 URL Rewrite 的出站规则(outboundRules)改写 RESPONSE_Location。出站规则是在响应发出前对响应头做纯文本正则替换,不走 URL 补全逻辑,所以可以把协议和主机名剥掉,# 和查询串都能原样保留:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found" destination="/test/login/#/sso$Q" />
        <rewrite>
            <outboundRules>
                <rule name="LocationToRelative">
                    <match serverVariable="RESPONSE_Location" pattern="^https?://[^/]+(/.*)" />
                    <action type="Rewrite" value="{R:1}" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

实测效果(curl -I http://localhost:8099/some/old/path?ticket=abc123):

# 加规则前
Location: http://localhost:8099/test/login/#/sso?ticket=abc123

# 加规则后
Location: /test/login/#/sso?ticket=abc123

注意:完整版 IIS 默认不带 URL Rewrite 模块,需要单独安装:https://www.iis.net/downloads/microsoft/url-rewrite (IIS Express 自带)。

这个出站规则对任何来源的重定向响应都生效(包括后端应用自己发出的 302),所以它也是反向代理场景下修正 Location 头的通用做法。

参考:

posted @ 2026-07-27 15:57  不是豆豆  阅读(5)  评论(0)    收藏  举报
友情链接:迷途