使用http module 对url进行重写的尝试

  因为一些原因,要将原来两个独立的站点(假设为dh.site.com和cd.site.com)放到同一个站点的两个application下,分别为(www.site.com/dh和www.site.com/cd)。

  因为在开发的时候,大部分静态文件的引用路径都是采用绝对路径的形式,例如/style/css1.css。可想而知,当将两个站点作为两个application放置后,这些静态文件就变得无法访问了,因为文件真实的路径已经变成了/dh/style.css1.css了。解决这个问题的最直接的方法就是修改所有的绝对路径:要么将原来的路径加上application的虚拟根路径(例如将/style.css1.css变成/dh/style.css1.css),要么改成相对路径。但无论如何,直接修改路径的方式都要找出散布在各个角落里的路径查找出来,再进行修改。虽然利用IDE的查找替换功能可以很快将路径查找出来,但也难免查找不完全,另一方面,如果路径数量非常多,则不得不花费大量时间去修改并且在修改后进行检查排错。

  尝试一:使用http module进行路径重写。

    这也是非常直接地联想到的方法:使用http module(可以使用url rewriter,或者自己编写一个http module)对正在进行访问的url进行重写到正确的路径。但这使用http module进行重写会有一个问题:只能用作重写静态文件请求,而对于aspx之类的动态文件的请求,因为在IIS6或以上,不同应用程序运行在不同的应用程序域(app domain)中,因此对动态文件的请求进行重写转跳,会发现两个转跳对象的session根本不同,或者根本不能加载类型(root application可以加载子application的类型)。这无论从网站安全角度,还是程序都安全角度来说,都是合理的。

  因为这里需要自定义更多的东西,因此需要自己编写一个http module,而不是使用url rewriter。思路如下:因为cd和dh中的静态文件都是指向到虚拟根目录的,因此需要在站点的root application中使用该http module。而在http module中,根据静态文件请求的referrer来判断请求时来自dh还是cd,然后再重定向到dh或者cd下相对应的文件。

  http module中的代码:

public class RedirectModule : IHttpModule
    {
        //定义静态文件的扩展名数组
        static string[] staticsFilesExName=new string[]{".jpg",".jepg",".gif",".png",".css",".html",".js"};
        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            if (app.Context.Request.UrlReferrer != null)
            {
                //取得页面的referrer,进行判断请求是来自www.site.com/dh还是来自www.site.com/cd
                string referrer = app.Context.Request.UrlReferrer.AbsoluteUri;

                //取得application root path部分,也就是http://www.site.com/dh中的"/dh"部分
                string appRootPath = referrer.Substring(23, 3);

                string rawUrl = app.Request.RawUrl;
                //得到转跳的url
                string reUrl = appRootPath + rawUrl;

                string extendName = app.Request.Path.Substring(app.Request.Path.LastIndexOf("."));

                //判断请求的对象是否为静态文件,是则转跳。
                if (RedirectModule.staticsFilesExName.Contains(extendName.ToLower()))
                {
                    app.Context.RewritePath(reUrl);
                }
            }
        }

        public void Dispose()
        {
            
        }
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }
    }

  注:在IIS7.5中,为了能使http module正常工作,除了在web.config/httpModules节下添加http module外,必须将站点的应用程序池版本.net framework版本设置为V2.0,并且将托管管道模式设置经典(classic),此外,还可能需要在system.webServer/handlers节中添加配置:

<add name="wildcard" path="*" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="None" preCondition="classicMode,runtimeVersionv2.0,bitness32" />

 

  然而,虽然使用http module能解决静态文件访问的问题,但不能重写动态文件,所以这不是个完美的解决方案。当然,如果动态文件的url数量少,手动改起来工作也不大的话,这也是个可以接受的方法。

  另外,可以考虑一下使用isapi filter来实现请求url重写,而且因为不同于http module要受到.net的限制,isapi filter运行在IIS层次之中,是否能突破应用程序池的限制,重定向的文件能顺利被执行(就如同该请求事来自浏览器一样)?

 

posted on 2013-01-11 00:08  wyman25  阅读(2423)  评论(6编辑  收藏  举报

导航