IIS 8.5跨站点URL重写后自定义HTTP头冲突问题解决方案咨询
好问题!咱们先直接说结论:你想要的「重写后仅应用test2的web.config配置」这个需求,在当前的URL Rewrite反向代理模式下无法直接实现,但有两个靠谱的替代方案可以解决CSP冲突的问题,咱们一步步说:
为什么当前配置不生效?
你用<location path="." inheritInChildApplications="false">的思路是对的,但这个标签是用来阻止子应用程序继承父站点配置的,而你的场景是通过URL Rewrite把请求反向代理到另一个独立站点,并不是子应用关系,所以这个配置完全不起作用。
本质上,当你用Rewrite类型的规则时,请求还是会先经过test1站点的处理管道——test1会先加载自己的web.config并添加自定义HTTP头,然后再把请求转发到test2;test2处理完返回响应后,test1会把自己的头和test2的头合并后返回给用户,这就导致了两个CSP头共存的问题。
可行解决方案
方案1:添加出站规则移除test1的CSP头
这是最贴近你需求的方案:通过IIS的URL Rewrite出站规则,在响应返回给用户之前,移除test1站点添加的CSP头,只保留test2返回的头。
在test1的web.config里,把这段代码加到<system.webServer><rewrite>节点下:
<outboundRules rewriteBeforeCache="true"> <rule name="Remove Test1 CSP for App Path" enabled="true"> <match serverVariable="RESPONSE_Content_Security_Policy" pattern=".*" /> <conditions> <!-- 仅针对/app开头的路径生效 --> <add input="{REQUEST_URI}" pattern="^/app(/.*)?$" /> </conditions> <action type="Rewrite" value="" /> </rule> </outboundRules>
这个规则会检测请求路径是否是/app开头,如果是,就清空test1的CSP响应头,最终用户只会收到test2的CSP头,完美解决冲突。
方案2:针对/app路径单独配置宽松CSP
如果出站规则的方式对你不适用,你可以在test1的web.config里,给/app路径单独配置和test2一致的CSP,覆盖全局的严格规则:
<location path="app"> <system.webServer> <httpProtocol> <customHeaders> <!-- 替换成test2的CSP规则 --> <add name="Content-Security-Policy" value="default-src 'self' ...; script-src ...;" /> </customHeaders> </httpProtocol> </system.webServer> </location>
这样当用户访问test1.mydomain.com/app时,会应用这个宽松的CSP,和test2的规则匹配,就不会出现脚本/样式加载失败的问题了。
额外说明:为什么不改成Redirect?
如果你把Rewrite规则改成Redirect(跳转),用户浏览器会直接访问test2的域名,自然只会有test2的头,但这样URL会从test1.mydomain.com/app变成test2.mydomain.com,如果你的需求是保持URL不变,这个方案就不适用。
内容的提问来源于stack exchange,提问作者Alfie Woodland

