RewriterURL实现二级域名的访问
在这里与大家分享一下URL的重写来实现二级域名的访问,这个方法也是在参与项目中学习到。平自己的理解来给大家分享,若有不对还请指出。
大家也知道Asp.Net的生命周期,当客户端请求时,经过IIS解析再到.NET Framework获得请求。在framework中就要进行一系列的处理,然后再返回给IIS最后在到客户端。我暂时知道两种处理URL重写。一种是在Global.asax里来实现,在web.config配置一下就可以实现了;另一种就是接下要写的。
我大概讲下实现思路:
写一个基类继(BaseModelRewriter.cs)承接口(IHttpModule),并且在这个基类写一个abstract RewriterURL();在写一个子类(ModeRewriter.cs)继承基类,并实现oerride Rewriter()接下来我们要重写这个方法;
要写一个方法我们就要做好一些准备,创建一个可序列化的类(ReWriterRule.cs)并以[Serializable()]标记还继承了类(CollectionBase),再写一个类(RewriterConfiguration.cs)主要是定义在Web.config文件中重写配置文件的结构; 再创建一个类(RewriterConfigSerializerSectionHandler.cs)来反序列化标记在Web.config为实例的,它继承接口(IConfigurationSectionHandler);在创建一个类(RewriterFactoryHandler.cs)并继承接口(IHttpHandlerFactory)提供了一个HttpHandler执行重定向。
最后我们还要配置一个web.config就可以实现功能了。还有IIS还要做下泛域名解析。如:xxx.like.com 做配置一下*.like.com;
实现代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 抽象类 模块重写基类。这类是抽象的,因此必须从。
/// </summary>
public abstract class BaseModelRewriter : IHttpModule
{
/// <summary>
/// 实现接口
/// </summary>
public virtual void Dispose()
{
}
/// <summary>
/// 实现接口
/// </summary>
/// <param name="context">一个参考的HttpApplication对象处理这个请求</param>
public virtual void Init(HttpApplication context)
{
//这并不与Windows身份验证的工作!
//如果您使用的是Windows身份验证,改变app.beginrequest
context.AuthorizeRequest += new EventHandler(this.BaseModelRewriter_AuthoriaeRequest);
}
/// <summary>
/// 当模块的authorizerequest事件触发。
/// </summary>
/// <param name="sender">该事件处理程序调用的<看到CREF =“改写”/>方法,通过在和HttpApplication通过通过发送者参数以上结果由</param>
/// <param name="e"></param>
protected virtual void BaseModelRewriter_AuthoriaeRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
Rewriter(app.Request.Url.AbsoluteUri,app);
}
/// <summary>
/// 该重写必须重写的方法。它是在重写传入的逻辑
/// URL 进行
/// <param name="requestedPath">所请求的rawurl。(包括完整的路径和查询字符串。)</param>
/// <param name="app">HttpApplication 实例 </param>
/// </summary>
protected abstract void Rewriter(string requestedPath,HttpApplication app);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 提供了一个重写Web应用。
/// </summary>
public class ModeRewriter : BaseModelRewriter
{
/// <summary>
/// 这种方法是模块BeginRequest事件中调用。
/// </summary>
/// <param name="requestedPath">被请求的rawurl(包括路径和查询字符串)</param>
/// <param name="app">HttpApplication实例。</param>
protected override void Rewriter(string requestedPath, HttpApplication app)
{
//将本地域名替换成服务域名来匹配
if (requestedPath.IndexOf("localhost") > 0 || requestedPath.IndexOf("192.168.0.3") > 0)
{
requestedPath = requestedPath.Replace("http://" + app.Request.ServerVariables["HTTP_HOST"], "www.like.com");//把主机名替换为www.baidu.com
}
else
{
requestedPath = requestedPath.Replace("http://" + app.Request.ServerVariables["HTTP_HOST"] + app.Request.ApplicationPath, "http://www.like.com");
}
//将html,xml以外的所有请求,直接返回,不去匹配
string ftypeRule = @"^*\.(js|jpg|gif|png|css|swf|ico)$";
Regex reFile = new Regex(ftypeRule, RegexOptions.IgnoreCase);
if (reFile.IsMatch(requestedPath.ToLower()))
{
return;
}
//日志信息跟踪对象
app.Context.Trace.Write("ModuleRewriter", "Entering ModuleRewriter");
//获取配置规则
RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules;
for (int i = 0; i < rules.Count; i++)
{
string LookFor = "^" + rules[i].LookFor + "$";
//正则表达式
Regex res = new Regex(LookFor, RegexOptions.IgnoreCase);
if (res.IsMatch(requestedPath))
{
//找到的匹配-做任何需要更换
string senderToUrl = RewriterUtils.RewriterUrl(app.Context.Request.ApplicationPath, res.Replace(requestedPath, rules[i].SenderTo));
//日志信息跟踪对象
app.Context.Trace.Write("ModuleRewriter", "Rewriting URL to " + senderToUrl);
RewriterUtils.RewriterUrl(app.Context, senderToUrl);
break;
}
}
//日志信息跟踪对象
app.Context.Trace.Write("ModuleRewriter", "Exiting ModuleRewriter");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 代表一个重写规则。一个重写规则是由一个模式搜索和替换字符串利用模式(配)。
/// </summary>
[Serializable()]
public class ReWriterRule
{
/// <summary>
/// 获得或者设置模式寻找
/// </summary>
public string LookFor { get; set; }
/// <summary>
/// 替换字符
/// </summary>
public string SenderTo { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 在Web.config文件的一组rewriterrules的rewriterrulecollection模型。
/// 该rewriterrulecollection表示XML:
/// <RewriterRule>
/// <LookFor><i>pattern to search for</i></LookFor>
/// <SendTo><i>string to redirect to</i></LookFor>
/// <RewriterRule>
/// <RewriterRule>
/// <LookFor><i>pattern to search for</i></LookFor>
/// <SendTo><i>string to redirect to</i></LookFor>
/// <RewriterRule>
/// ...
/// <RewriterRule>
/// <LookFor><i>pattern to search for</i></LookFor>
/// <SendTo><i>string to redirect to</i></LookFor>
/// <RewriterRule>
/// </summary>
[Serializable()]//标记可能序列化类
public class RewriterRuleCollection : CollectionBase
{
//增加了一个新的rewriterrule到集合。
public virtual void Add(ReWriterRule r)
{
this.InnerList.Add(r);
}
//获取或设置在一个指定的序号索引一个rewriterrule
public ReWriterRule this[int index]
{
get {
return (ReWriterRule) this.InnerList[index];
}
set {
this.InnerList[index] = value;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Xml.Serialization;
using System.Xml.XPath;
using System.Xml;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 反序列化标记在Web.config为实例的<看到CREF =“rewriterconfiguration”/>类。
/// </summary>
public class RewriterConfigSerializerSectionHandler : IConfigurationSectionHandler
{
/// <summary>
/// 创建一个实例
/// </summary>
/// <param name="parent"></param>
/// <param name="configContext"></param>
/// <param name="section"></param>
/// <returns></returns>
public virtual object Create(object parent, object configContext, System.Xml.XmlNode section)
{
//创建一个基于rewriterconfiguration型XmlSerializer实例。
XmlSerializer ser = new XmlSerializer(typeof(RewriterConfiguration));
//返回反序列化的对象从web.config XML
return ser.Deserialize(new XmlNodeReader(section));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text.RegularExpressions;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 提供了一个HttpHandler执行重定向。
/// 该rewriterfactoryhandler检查重写规则重写路径,如果需要的话,然后代表处理ASP.NET页责任到
/// pageparser (同一类由 pagehandlerfactory 类使用)。
/// </summary>
public class RewriterFactoryHandler : IHttpHandlerFactory
{
/// <summary>
/// 那么GetHandler由ASP.NET管道后相关的HttpModules跑。的工作那么GetHandler是返回一个HttpHandler可以处理该页的一个实例。
/// </summary>
/// <param name="context">这是一个请求HttpContext</param>
/// <param name="requestType">的HTTP数据传输方法(<b>得到</b>或<b>后</b>)</param>
/// <param name="url">所请求的资源rawurl</param>
/// <param name="pathTranslated">所请求的资源的物理路径</param>
/// <returns>实现IHttpHandler的实例;具体地说,一个HttpHandler实例返回由<b> pageparser
/// </b>类,这是默认的ASP.NET pagehandlerfactory代表同一类对。</returns>
public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
//日志信息的跟踪对象。
context.Trace.Write("RewriterFactoryHandler", "Entering RewriterFactoryHandler");
string senderToURL = url;
string filePath = pathTranslated;
//获取配置规则
RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules;//该方法是读取web.config配置文件中取规则集合,并且使用了cache缓存以避免频繁IO操作
//遍历规则
for (int i = 0; i < rules.Count; i++)
{
string lookFor = "^" + RewriterUtils.RewriterUrl(context.Request.ApplicationPath, rules[i].LookFor) + "$";
//创建一个正则表达式对象的情况下,忽略了…
Regex reg = new Regex(lookFor, RegexOptions.IgnoreCase);
//看看我们找到一个匹配
if (reg.IsMatch(url))
{
//做任何需要更换
senderToURL = RewriterUtils.RewriterUrl(context.Request.ApplicationPath, reg.Replace(url, rules[i].SenderTo));
//日志信息的跟踪对象…
context.Trace.Write("RewriterFactoryHandler", "Found match, rewriting to " + senderToURL);
//重写路径,得到更少的URL和查询字符串的物理文件路径
string senderToUrlLessQString = string.Empty;
RewriterUtils.RewriterUrl(context, senderToURL, out senderToUrlLessQString, out pathTranslated);
//返回的页面编译的版本
context.Trace.Write("RewriterFactoryHandler", "Exiting RewriterFactoryHandler");//日志信息的跟踪对象…
return PageParser.GetCompiledPageInstance(url, filePath, context);
}
}
//如果我们达到这一点,我们没有找到一个改写比赛
context.Trace.Write("RewriterFactoryHandler", "Exiting RewriterFactoryHandler");//日志信息的跟踪对象…
return PageParser.GetCompiledPageInstance(url, filePath, context);
}
public virtual void ReleaseHandler(IHttpHandler handler)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ElToolsTest.URLWriter
{
/// <summary>
/// 提供用于重写Web应用和HttpHandler实用的辅助方法。
/// 这类标记为内部,意义在同一组件只有类可以访问它的方法
/// </summary>
internal class RewriterUtils
{
/// <summary>
/// 重写的URL使用HttpContext。rewriteurl()
/// </summary>
/// <param name="context">HttpContext对象重写URL。</param>
/// <param name="senderToUrl">URL重写。</param>
internal static void RewriterUrl(HttpContext context, string senderToUrl)
{
string x, y;
RewriterUrl(context, senderToUrl, out x, out y);
}
/// <summary>
/// 重写的URL使用 HttpContext。rewriteurl()
/// </summary>
/// <param name="context">HttpContext对象重写URL。</param>
/// <param name="senderToUrl">URL重写。</param>
/// <param name="senderToUrlLessQstring">返回sendertourl剥离的查询字符串值</param>
/// <param name="param name="filePath"">返回所请求页面的物理文件路径</param>
internal static void RewriterUrl(HttpContext context, string senderToUrl, out string senderToUrlLessQstring, out string filePath)
{
//看看我们是否需要添加任何额外的查询字符串信息
if (context.Request.QueryString.Count > 0)
{
if (senderToUrl.IndexOf("?") != -1)
{
senderToUrl += "@" + context.Request.QueryString.ToString();
}
else
{
senderToUrl += "?" + context.Request.QueryString.ToString();
}
}
//第一条查询字符串,如
string queryString = string.Empty;
senderToUrlLessQstring = senderToUrl;
if (senderToUrl.IndexOf('?') > 0)
{
senderToUrlLessQstring = senderToUrl.Substring(0, senderToUrl.IndexOf('?'));
queryString = senderToUrl.Substring(senderToUrl.IndexOf('?') + 1);
}
//获取文件的物理路径
filePath = string.Empty;
filePath = context.Server.MapPath(senderToUrlLessQstring);
//重写路径
context.RewritePath(senderToUrlLessQstring, string.Empty, queryString);
/*
注!上述rewritepath()过载只能在。NET框架1.1
如果您使用的是。NET框架1,使用下面的表格代替:
语境rewritepath(sendtourl);
*/
}
/// <summary>
/// 将URL到一个在请求客户端可用的。
/// 将~给请求的应用程序的路径。模仿的行为
/// 控制。resolveurl() 方法,这往往是由控件开发人员使用。
/// </summary>
/// <param name="appPath">应用程序路径</param>
/// <param name="url"></param>
/// <returns>一个解决的URL。如果输入参数URL 包含~,取代它的是与的 apppath 参数值。</returns>
internal static string RewriterUrl(string appPath, string url)
{
if (url.Length == 0 || url[0] != '~')
{
return url;//在第一个字符的位置没有~,刚刚返回的URL
}
else
{
if (url.Length == 1)
{
return appPath;//只有在网址中的~,返回apppath
}
if (url[1] == '/' || url[1] == '\\')
{
//URL看起来像~ /或~ \
if (appPath.Length > 1)
{
return appPath + "/" + url.Substring(2);
}
else
{
return "/" + url.Substring(2);
}
}
else
{
//~ URL看起来像什么
if (appPath.Length>1)
{
return appPath + "/" + url.Substring(1);
}
else
{
return "/" + url.Substring(1);
}
}
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细消息,请访问
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!--
< configsections >元素必须包含一个<第>
标签为< rewriterconfig >节元素。
本节处理程序类型是rewriterconfigserializersectionhandler,这是负责反序列化<rewriterconfig >节元素为rewriterconfig实例。
-->
<section name="RewriterConfig" type="ElToolsTest.URLWriter.RewriterConfigSerializerSectionHandler"/>
</configSections>
<RewriterConfig>
<Rules>
<ReWriterRule>
<LookFor>http://(www\.|)baidu.com/Login.htm</LookFor>
<SenderTo><![CDATA[~/test.htm]]></SenderTo>
</ReWriterRule>
</Rules>
</RewriterConfig>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpHandlers>
<add verb="*" path="*.html" type="ElToolsTest.URLWriter.RewriterFactoryHandler"/>
</httpHandlers>
<httpModules>
<add name="ModeRewriter" type="ElToolsTest.URLWriter.ModeRewriter" />
</httpModules>
</system.web>
</configuration>
代码里有变量可以自己变更即可。若有不对之处还请指出,谢谢!
浙公网安备 33010602011771号