(文章轉(zhuǎn)自cxbkkk,為了方便瀏覽,直接將文章粘了過來,我只是根據(jù)這個文章,建了測試項目,將代碼發(fā)布上來,供自己和剛剛接觸地址重寫的人看看。
項目環(huán)境是vs2008,測試項目訪問如Http://www.abc.com/1.aspx 則會顯示theid is 1)原文出處:http://www.cnblogs.com/cxbkkk/archive/2006/11/27/574434.html這個系列已經(jīng)很久沒寫了,因為太懶了。今天想起還是寫一些東西,雖然這個用了很久了,但是也可以再看看。 之前在轉(zhuǎn)貼中說到了UrlRewrite這一技術(shù),這個技術(shù)的實質(zhì)就是通過獲取當前Url地址匹配對應的規(guī)則,傳遞給真實的訪問頁面。而這一技術(shù)帶來的是相對的安全以及訪問的便利。從我個人的理解來看,就是讓人可以通過簡單的方便的方式來訪問,對一部分人來說是不讓其知道具體的真實頁面。 從轉(zhuǎn)貼中了解到,要實現(xiàn)這個功能要么自定義HTTP模塊類,要么通過ISAPI來實現(xiàn),相對來說前者更具有通用性以及擴展性。 要實現(xiàn)自定義HTTP模塊類則要實現(xiàn)接口IHttpModule,它其中有Init方法,同時要實現(xiàn)Init中參數(shù)HttpApplication的AuthenticateRequest事件,以及我們定義的Rewrite的抽象方法。
public virtual void Init(HttpApplication app)
{
app.AuthorizeRequest += new EventHandler(this.BaseModuleRewriter_AuthorizeRequest);
}
public virtual void Dispose() { }
protected virtual void BaseModuleRewriter_AuthorizeRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
///一般重寫
Rewrite(app.Request.Path, app);
///二級域名重寫
//Rewrite(app.Request.Url.AbsoluteUri, app);
}
protected abstract void Rewrite(string requestedPath, HttpApplication app);
其中注釋掉的部分為二級域名重寫的方法,唯一的區(qū)別就是獲取的地址為絕對地址,因為一般重寫即是:www.abc.com/123/實際訪問為www.abc.com/index.aspx?id=123,而二級域名重寫則是:123.abc.com實際訪問為www.abc.com/index.aspx?id=123。這兩個雖然結(jié)果是一樣的,但是他們的實現(xiàn)方法是不同的。要實現(xiàn)二級域名重寫首先就是要域名支持泛解析,所謂泛解析就是不論是123.abc.com、abc.com、abc123.abc.com都訪問的是http://www.abc.com/,這個也是二級域名實現(xiàn)的基礎。因為在傳遞真實的地址的時候就是通過泛解析來讓地址進入http://www.abc.com/再加上后面的index.aspx?id=123。 上面定義了重寫的抽象方法,現(xiàn)在我就要來實現(xiàn)這個重寫方法,流程則是讀取xml或者Config中對應的正則來匹配獲取的Url地址,然后傳遞到真實的地址,所以我就還要實現(xiàn)幾個方法,第一個是讀取Config或Xml中對應的正則以及真實地址的方法,第二個是對讀取出來的數(shù)據(jù)分離出正則和真實地址,第三個為了方便在重寫的時候快速的對其匹配對第二個分離的數(shù)據(jù)進行集合。 上面的我統(tǒng)一命名空間為Rewrite.config,我們還要實現(xiàn)匹配后傳遞地址的過程。 按照取Url-->匹配正則-->傳遞地址,這樣的過程實現(xiàn)。
1 protected override void Rewrite(string requestedPath, System.Web.HttpApplication app)
2 {
3 RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules;
4
5 for (int i = 0; i < rules.Count; i++)
6 {
7 ///一般重寫
8 string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].LookFor) + "$";
9 ///二級域名重寫
10 //string lookFor = "^" + rules[i].LookFor + "$";
11
12 Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);
13
14 if (re.IsMatch(requestedPath))
15 {
16 string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].SendTo));
17
18 app.Context.Trace.Write("ModuleRewriter", "Rewriting URL to " + sendToUrl);
19
20 RewriterUtils.RewriteUrl(app.Context, sendToUrl);
21 break; }
22 }
23
24 app.Context.Trace.Write("ModuleRewriter", "Exiting ModuleRewriter");
25 }
在匹配的時候就涉及到了使用什么樣的地址來匹配,二級域名因為使用的絕對地址,所以這里就不需要通過我們定義的方法Resolve來補充相對地址?,F(xiàn)在剩下的就是RewriteUtils中的地址補充以及地址傳遞。
1 internal static void RewriteUrl(HttpContext context, string sendToUrl)
2 {
3 string x, y;
4 RewriteUrl(context, sendToUrl, out x, out y);
5 }
6
7 internal static void RewriteUrl(HttpContext context, string sendToUrl, out string sendToUrlLessQString, out string filePath)
8 {
9
10 if (context.Request.QueryString.Count > 0)
11 {
12 if (sendToUrl.IndexOf('?') != -1)
13 sendToUrl += "&" + context.Request.QueryString.ToString();
14 else
15 sendToUrl += "?" + context.Request.QueryString.ToString();
16 }
17
18 string queryString = String.Empty;
19 sendToUrlLessQString = sendToUrl;
20 if (sendToUrl.IndexOf('?') > 0)
21 {
22 sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf('?'));
23 queryString = sendToUrl.Substring(sendToUrl.IndexOf('?') + 1);
24 }
25
26 filePath = string.Empty;
27 filePath = context.Server.MapPath(sendToUrlLessQString);
28
29 context.RewritePath(sendToUrlLessQString, String.Empty, queryString);
30 }
31
32 internal static string ResolveUrl(string appPath, string url)
33 {
34 if (url.Length == 0 || url[0] != '~')
35 return url;
36 else
37 {
38 if (url.Length == 1)
39 return appPath;
40 if (url[1] == '/' || url[1] == '\\')
41 {
42 if (appPath.Length > 1)
43 return appPath + "/" + url.Substring(2);
44 else
45 return "/" + url.Substring(2);
46 }
47 else
48 {
49 if (appPath.Length > 1)
50 return appPath + "/" + url.Substring(1);
51 else
52 return appPath + url.Substring(1);
53 }
54 }
55 }
然后就是對配置文件或Xml中添加訪問模塊的名稱,以及以讀取中定義的名稱為節(jié)點的正則匹配和傳遞地址。<configSections> <section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter.Config" /> </configSections><httpModules> <add type="URLRewriter.ModuleRewriter, URLRewriter" name="ModuleRewriter" /> </httpModules> 正則匹配為<RewriterConfig> <Rules> <!--一般重寫正則--> <RewriterRule> <LookFor>~/(\d+)\.aspx</LookFor> <SendTo>~/Default.aspx?theid=$1</SendTo> </RewriterRule> <!--二級重寫正則--> <!--<RewriterRule> <LookFor>http://(\d+)\.abc.com/</LookFor> <SendTo>/Default.aspx?theid=$1</SendTo> </RewriterRule>--> </Rules> </RewriterConfig> 到這里重寫就完成了,而其他重寫都是在這些基礎之上,應該可以通過組合之類的實現(xiàn)多種重寫。以上的東西希望可以讓你清晰的了解UrlRewrite的流程和原理。
源代碼下載:地址重寫