如何解决Azure/IIS上ASP.NET Core 7 MVC的IIS Rewrite意外重定向问题?
我们的ASP.NET Core 7 MVC应用部署在Azure和IIS上,为实现添加尾部斜杠的需求配置了URL重写规则,但出现了意外问题:当请求路径包含类似/http:/google.com的内容时,会触发规则跳转到外部网站(比如谷歌)。
具体场景:请求进入RewriteModule时格式为http://rockstar-dev-web-01:80/http:/google.com,但会被自动拆分为两部分,仅第二部分被处理。触发添加尾部斜杠的规则后,会产生301重定向,相关请求日志如下:
GENERAL_REQUEST_START SiteId="1922794053237", AppPoolId="rockstar-dev-web-01", ConnId="805308232052", RawConnId="8053080123152", RequestURL="http://rockstar-dev-web-01:80/https:/wp.pl", RequestVerb="GET" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="FailedRequestsTracingModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="FailedRequestsTracingModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="RequestMonitorModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="RequestMonitorModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="IsapiFilterModule" 20:16:22.600
FILTER_PREPROC_HEADERS_START 20:16:22.600
FILTER_START FilterName="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_filter.dll" 20:16:22.600
GENERAL_SET_REQUEST_HEADER HeaderName="AspFilterSessionId", HeaderValue="", Replace="true" 20:16:22.600
FILTER_SET_REQ_HEADER HeaderName="AspFilterSessionId:", HeaderValue="" 20:16:22.600
FILTER_END NotificationStatus="SF_STATUS_REQ_NEXT_NOTIFICATION" 20:16:22.600
FILTER_PREPROC_HEADERS_END 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="IsapiFilterModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="RewriteModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="RewriteModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="ARRHelper" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="ARRHelper", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="DynamicIpRestrictionModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="DynamicIpRestrictionModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="ProcessMonitoringModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="ProcessMonitoringModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="DWASModule" 20:16:22.600
GENERAL_SET_REQUEST_HEADER HeaderName="HOST", HeaderValue="develop.rockstar.com", Replace="true" 20:16:22.600
GENERAL_SET_REQUEST_HEADER HeaderName="x-ms-http-forward", HeaderValue="", Replace="true" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="DWASModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
PRE_BEGIN_REQUEST_START ModuleName="AzureSlaModule" 20:16:22.600
PRE_BEGIN_REQUEST_END ModuleName="AzureSlaModule", NotificationStatus="NOTIFICATION_CONTINUE" 20:16:22.600
GENERAL_REQUEST_HEADERS Headers="Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.5
Host: develop.rockstar.com
Max-Forwards: 10
TE: trailers
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0
DNT: 1
sec-gpc: 1
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: none
sec-fetch-user: ?1
X-ARR-LOG-ID: c57dc640-fe88-4a55-823c-3620113afe17
DISGUISED-HOST: develop.rockstar.com
X-SITE-DEPLOYMENT-ID: rockstar-dev-web-01
WAS-DEFAULT-HOSTNAME: rockstar-dev-web-01.azurewebsites.net
X-Forwarded-Proto: https
X-AppService-Proto: https
X-Forwarded-TlsVersion: 1.3
X-Original-URL: /https://wp.pl
X-WAWS-Unencoded-URL: /https://wp.pl
20:16:22.600
URL_CACHE_ACCESS_START RequestURL="/https:/wp.pl"
解决方案
1. 限制尾部斜杠规则的适用范围
修改重写规则,仅对**不包含协议前缀(http:/https:)**的路径添加尾部斜杠,避免误处理包含外部URL的路径。
在web.config的<rewrite>节点中添加以下规则(替换原有添加尾部斜杠的规则):
<rule name="Add trailing slash" stopProcessing="false"> <match url="(.*[^/])$" /> <conditions> <!-- 排除包含http:或https:前缀的路径 --> <add input="{REQUEST_URI}" pattern="^/http(s)?:" negate="true" /> <!-- 排除静态文件和目录(可选,根据业务需求调整) --> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Redirect" url="{R:1}/" redirectType="Permanent" /> </rule>
2. 前置拦截非法路径
如果这类包含外部URL的请求本身属于非法请求,可以添加前置规则直接拦截,避免进入后续重写逻辑。将此规则放在所有重写规则的最顶部:
<rule name="Block external URL paths" stopProcessing="true"> <match url="^http(s)?:" /> <action type="CustomResponse" statusCode="404" statusReason="Not Found" statusDescription="Invalid request path" /> </rule>
3. 启用URL规范化
利用Azure App Service或IIS的URL规范化功能,自动修正异常路径格式:
- Azure App Service:进入应用服务的「配置」→「常规设置」,开启「URL规范化」选项
- IIS:站点→URL重写→「视图服务器变量」,添加
HTTP_X_ORIGINAL_URL,后续规则可基于规范化后的URL进行处理
4. 配置路由约束
在ASP.NET Core的路由配置中添加约束,排除包含冒号的控制器/动作名称,避免路由误匹配异常路径。在Program.cs中修改路由配置:
app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}", constraints: new { controller = @"[^:]*", action = @"[^:]*" } );
内容的提问来源于stack exchange,提问作者MetalGearNotSoSolid

