• 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>
    

    代码里有变量可以自己变更即可。若有不对之处还请指出,谢谢!

  • 相关阅读:
    Linux 开发之线程条件锁那些事
    Linux 开发之线程条件锁那些事
    Linux 开发之线程条件锁那些事
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
  • 原文地址:https://www.cnblogs.com/LikeNeng/p/3780744.html
Copyright © 2020-2023  润新知