投稿 评论 顶部

ISAPI_Rewrite3.1于MVC站点下,在IIS7跳转成功,但在IIS6跳转失败,有后缀URL和有后缀URL处理方式不同。...

佚名 网络安全

文章来源:博客园

原创作者:pfdcnblogs

一、问题描述

老商铺使用Asp.NET Form,重构后使用Asp.NET MVC。需要对老商铺的链接进行跳转。
介于老商铺之前已经使用ISAPI_Rewrite3.1做过伪静态处理,跳转规则需要处理两种链接(老商铺的英文拼写是错误的-_-!):

localhost:8008/compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6localhost:8008/companyinfo.aspx?Uid=B5BD5324-D7CD-448A-A499-B01808CCFAB6

在IIS7下,使用以下跳转规则,没有问题:

RewriteRule    ^/compayinfo/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/?$                                /Home/Company/$1        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /Home/Company/$1        [NC]

但是在IIS6下,无法跳转。无奈准备将跳转规则硬编码进MVC路由。

悲催的是,写完代码调试的时候才发现,原来NVC的路由中不允许出现问号:

路由 URL 不能以“/”或“~”字符开头,并且不能包含“?”字符。

本来就觉得硬编码很不爽,现在又发现这种限制,马上回头查找IIS6下跳转失败的原因。

二、查找资料

在baidu了几篇,bing了十几篇,google被重置,后得知:

ASP.NET 4.0在安装的时候,会在IIS6注册一个ISAPI Filter,叫做”aspnet_filter.dll”,ISAPI Filter会先于ISAPI处理程序前执行,它会在所有的的无后缀的URL后面加一串字符“/eurl.axd/GUID”, 同时ASP.NET 4.0还会在IIS默认添加一个请求映射规则“*.axd”,映射到aspnet_isapi.dll。此时,所有的无后缀URL加上“/eurl.axd/GUID”后都会变成带.axd后缀,这样就匹配*.axd的映射规则进行ASP.NET的处理通道。在进入ASP.NET通道后,ASP.NET处理程序会删除掉“/eurl.axd/GUID”,让它还原到无后缀的原始情况,并且不会对后续的请求处理带来任何影响。此时,所有的无后缀请求,就进入了ASP.NET的处理通道中,在默认情况下,ASP.NET4.0的全局的web.config中配置了DefaultHttpHandler来接收无后缀的URL请求,但是我们也可以随意更换默认处理程序(比如ASP.NET MVC处理程序)来处理无后缀的URL请求。

提供的解决方案也无外乎:

修改注册表:
在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0(64位:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\4.0.30319.0)下,添加键值名为“EnableExtensionlessUrls” 类型为“DWORD”的键值,并设置值为“0”。然后在cmd中运行“IISRESET”,重启IIS以读取注册表修改后的内容。
注:此项修改就是关闭 ASP.NET 4?.0对无扩展URL的处理,若将此项键值设为“1”则开启。

或者使用.NET2的应用程序池,或者自定义一个重写模块。
问题是我连修改IIS的权限都没有,更何况注册表了。自定义重写模块也太麻烦了。

三、尝试解决

经过N多次尝试,推测出请求的处理顺序如下:

对于无后缀URL:compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6
1.首先被aspnet_filter处理为:compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6/eurl.axd/GUID
2.然后进入ISAPI_Rewrite,进行重定向
3.接着根据“*.axd”的映射规则将请求交给aspnet_isapi
4.进而在aspnet_isapi中移除后缀/eurl.axd/GUID
5.最后进行后续处理

可以看出,对于无后缀URL,在进行重定向时,需要处理被添加的后缀:

RewriteRule    ^/compayinfo/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(/eurl.axd/.*)$                                /Home/Company/$1$2        [NC]

测试成功!立马将该方法应用于有后缀URL,进行尝试,惨遭失败

RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /favicon.ico        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /Home/Company/$1        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(/eurl.axd/.*)$                        /Home/Company/$1        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /Home/Company/$1/eurl.axd/        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /Home/Company/$1/eurl.axd/0        [NC]RewriteRule    ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$                        /Home/Company/$1/eurl.axd0/        [NC]

?

第一条成功。
第二条失败,出现IIS404。
第三条失败,出现Asp.NET404,找不到/companyinfo.aspx。
第四条成功,但它匹配到了我的一条路由规则“{controller}/{action}/{Identifie}/{id}”,其中id的值为“eurl.axd”
第五条失败,出现Asp.NET404,找不到/Home/Company/B5BD5324-D7CD-448A-A499-B01808CCFAB6/eurl.axd/0。
第六条失败,出现IIS404。

?


注:?

以上内容编辑于2013-09-24 11:13,但一直放在草稿箱中忘了发布,今天才看到,发布一下。

另外,对于有后缀URL,因时间有限且并不特别需要,后并未深入研究。