惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - kkk

无题 重出江湖! 今天周末休息一天,发贴! 转贴:ASP.NET 2.0 中改进的缓存功能 一个多月来第一贴! 怀念一下《幽灵公主》 惊悚科幻 《灵幻夹克》 西安归来!(终于写完了) 支付宝Payto接口的c#.net实现 关于MD5码的一些自我总结 再总结一些技巧 超准的爱情测验! 转贴:Oracle(甲骨文)的CEO Larry.Ellison在耶鲁大学2000届毕业典礼上的演讲 转贴:出租车司机给微软高管上的MBA课程! 80个Gmail帐号,5个Live Messenger试用邀请,要的留言并注明是什么的邀请! 新年新贴! 关于asp.net c#中对cookie的操作 - kkk - 博客园 回滚事务日志文件中的事务 转贴:ASP.NET中的UrlRewrite
技巧百问(10):UrlRewrite以及二级UrlRewrite
kkk · 2006-11-27 · via 博客园 - kkk

        这个系列已经很久没写了,因为太懒了。今天想起还是写一些东西,虽然这个用了很久了,但是也可以再看看。
        之前在转贴中说到了UrlRewrite这一技术,这个技术的实质就是通过获取当前Url地址匹配对应的规则,传递给真实的访问页面。而这一技术带来的是相对的安全以及访问的便利。从我个人的理解来看,就是让人可以通过简单的方便的方式来访问,对一部分人来说是不让其知道具体的真实页面。
         从转贴中了解到,要实现这个功能要么自定义HTTP模块类,要么通过ISAPI来实现,相对来说前者更具有通用性以及扩展性。
         要实现自定义HTTP模块类则要实现接口IHttpModule,它其中有Init方法,同时要实现Init中参数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);

         其中注释掉的部分为二级域名重写的方法,唯一的区别就是获取的地址为绝对地址,因为一般重写即是:www.abc.com/123/实际访问为www.abc.com/index.aspx?id=123,而二级域名重写则是:123.abc.com实际访问为www.abc.com/index.aspx?id=123。这两个虽然结果是一样的,但是他们的实现方法是不同的。要实现二级域名重写首先就是要域名支持泛解析,所谓泛解析就是不论是123.abc.com、abc.com、abc123.abc.com都访问的是www.abc.com,这个也是二级域名实现的基础。因为在传递真实的地址的时候就是通过泛解析来让地址进入www.abc.com再加上后面的index.aspx?id=123。
         上面定义了重写的抽象方法,现在我就要来实现这个重写方法,流程则是读取xml或者Config中对应的正则来匹配获取的Url地址,然后传递到真实的地址,所以我就还要实现几个方法,第一个是读取Config或Xml中对应的正则以及真实地址的方法,第二个是对读取出来的数据分离出正则和真实地址,第三个为了方便在重写的时候快速的对其匹配对第二个分离的数据进行集合。

  1 //以下代码为读取数据,并加入到集合中
  2 public class RewriterConfigSerializerSectionHandler : IConfigurationSectionHandler
  3     {
  4         public object Create(object parent, object configContext, System.Xml.XmlNode section)
  5         {
  6             XmlSerializer ser = new XmlSerializer(typeof(RewriterConfiguration));
  7 
  8             return ser.Deserialize(new XmlNodeReader(section));
  9         }
 10 
 11 [Serializable()]
 12     [XmlRoot("RewriterConfig")]//这里可以随便定义,主要通过这个名字的节点来获取正则匹配。cxbkkk
 13     public class RewriterConfiguration
 14     {
 15         
 16         private RewriterRuleCollection rules;  
 17         public static RewriterConfiguration GetConfig()
 18         {
 19             if (HttpContext.Current.Cache["RewriterConfig"== null)
 20                 HttpContext.Current.Cache.Insert("RewriterConfig", ConfigurationSettings.GetConfig("RewriterConfig"));
 21 
 22             return (RewriterConfiguration)HttpContext.Current.Cache["RewriterConfig"];
 23         }
 24 
 25         #region Public Properties
 26         /// <summary> 
 27         /// 正则匹配集合
 28         /// </summary> 
 29         public RewriterRuleCollection Rules
 30         {
 31             get
 32             {
 33                 return rules;
 34             }
 35             set
 36             {
 37                 rules = value;
 38             }
 39         }
 40         #endregion
 41     } 
 42 
 43 public class RewriterRule
 44     {
 45         private string lookFor, sendTo;
 46 
 47         public string LookFor
 48         {
 49             get
 50             {
 51                 return lookFor;
 52             }
 53             set
 54             {
 55                 lookFor = value;
 56             }
 57         }
 58 
 59 
 60         public string SendTo
 61         {
 62             get
 63             {
 64                 return sendTo;
 65             }
 66             set
 67             {
 68                 sendTo = value;
 69             }
 70         }
 71 
 72     } 
 73 
 74 [Serializable()]
 75     public class RewriterRuleCollection : CollectionBase
 76     {
 77         /// <summary> 
 78         /// 加入一个新匹配到集合. 
 79         /// </summary> 
 80     
 81         public virtual void Add(RewriterRule r)
 82         {
 83             this.InnerList.Add(r);
 84         }
 85 
 86         /// <summary> 
 87         /// 集合的索引. 
 88         /// </summary> 
 89         public RewriterRule this[int index]
 90         {
 91             get
 92             {
 93                 return (RewriterRule)this.InnerList[index];
 94             }
 95             set
 96             {
 97                 this.InnerList[index] = value;
 98             }
 99         }
100     } 
101 
102     } 

          上面的我统一命名空间为Rewrite.config,我们还要实现匹配后传递地址的过程。
           按照取Url-->匹配正则-->传递地址,这样的过程实现。

 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来补充相对地址。现在剩下的就是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中添加访问模块的名称,以及以读取中定义的名称为节点的正则匹配和传递地址。
<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>

               到这里重写就完成了,而其他重写都是在这些基础之上,应该可以通过组合之类的实现多种重写。以上的东西希望可以让你清晰的了解UrlRewrite的流程和原理。


参考:
         MSDN