• 管道处理模型二(摘抄cainong2005博客)


    一.Httphandler:

    在《模型一》的demo中,新建一个webform文件,MyWebForm.aspx,内容和简单,就是一行文字。

    1.  
      <body>
    2.  
      <form id="form1" runat="server">
    3.  
      <div>
    4.  
      This is MyWebForm
    5.  
      </div>
    6.  
      </form>
    7.  
      </body>

     运行结果:

    再看MyWebForm.aspx.cs文件代码:

    1.  
      public partial class MyWebForm : System.Web.UI.Page
    2.  
      {
    3.  
      protected void Page_Load(object sender, EventArgs e)
    4.  
      {
    5.  
       
    6.  
      }
    7.  
      }

    没有别的代码,只是实现了System.Web.UI.Page,Page又是什么呢?F12跟进去:

    所以,在Webform中,我们申明的东西,写的页面,实现的业务逻辑,其实就是一个HttpHandler,而它是在PreRequestHandlerExecute 和 PostRequestHandlerExecute 这两个Event之间执行的。

    这里有一个很重要的事件,MapRequestHandler,负责制定具体的handler处理请求:

    它是在哪里配置的呢?

    全局的webconfig中,(C:WindowsMicrosoft.NETFramework64v4.0.30319Configweb.config)

    我们先用反编译工具,看看System.Web.UI.PageHandlerFactory:

    这个核心方法 GetHandlerHelper干什么的呢?它就是传入的参数,创建一个Page。

    其实从名字就能看的出来,PageHandlerFactory,PageHandler的工厂,当然输出Page。

    还有web.config文件不能访问,就是因为已经配置了HttpForbiddenHandler,禁止访问。

    强行访问web.config,就报错了

    为什么禁止访问?HttpForbiddenHandler里面做了什么?反编译工具中看:

    既然知道了怎么给不同后缀名的请求配置不同处理的HttpHandler,那我们能不能自定义呢?可以的。例如自定义一个图片验证码请求的HttpHandler。步骤如下:

    1.webconfig下,在handlers节点配置一个处理verify后缀的HttpHandler。

    2.建立VerifyCode类,并继承IHttpHandler,这个 是必须的。

    3.在浏览器中访问 http://localhost:8090/handler/1.verify ,报错

    错误很明显,是不存在handler控制器,那么在路由里面将它忽略掉吧。

    4.忽略路由:

    5.浏览器再次访问 http://localhost:8090/handler/1.verify ,显示了正确的验证码图片。

    问题来了,这样自定义HttpHandler有什么价值?举个例子,可以做防盗链。

    比如网上有很多图片“本图片仅限百度用户内部交流”,这就是百度图片做了防盗链,怎么做到的呢?就是用到了自定义的HttpHandler。步骤如下:

    1.在web.config文件的  节点,针对图片类型,注册新的HttpHandler。

    2.在PipeController控制器中加一个Handler()方法。

    1.  
      public ViewResult Handler()
    2.  
      {
    3.  
      IHttpHandler handler = base.HttpContext.Handler;
    4.  
      ViewBag.HandlerName = handler.GetType().ToString();
    5.  
      ViewBag.Url = Request.Url.AbsoluteUri;
    6.  
      return View();
    7.  
      }

    同时,Handler.cshtml中也添加代码。

    1.  
      @{
    2.  
      ViewBag.Title = "Handler";
    3.  
      }
    4.  
       
    5.  
      <h2>Handler</h2>
    6.  
      <p>@ViewBag.HandlerName</p>
    7.  
      <p>@ViewBag.Url</p>
    8.  
      <p>@Html.Image("/Content/Image/liuyan.jpg", "liuyan图片", "柳岩", new { id = "image" })</p>

    运行一下,显示如图:

    3.F12打开浏览器的调试工具,看到了原图地址:

    4.既然已经找到了原图地址,在浏览器的新标签页打开,结果是这个样子:

    由此可见,直接输入图片地址是打不开的,也达到了防盗链的效果。下面讲一下是如何做到的

    看看上面定义的ImageHandler类的ProcessRequest方法:

    1.  
      public void ProcessRequest(HttpContext context)
    2.  
      {
    3.  
      // 如果UrlReferrer为空,则显示一张默认的禁止盗链的图片
    4.  
      if (context.Request.UrlReferrer == null || context.Request.UrlReferrer.Host == null)
    5.  
      {
    6.  
      context.Response.ContentType = "image/JPEG";
    7.  
      context.Response.WriteFile("/Content/Image/Forbidden.jpg");
    8.  
      }
    9.  
      else
    10.  
      {
    11.  
      // 如果 UrlReferrer中不包含自己站点主机域名,则显示一张默认的禁止盗链的图片
    12.  
      if (context.Request.UrlReferrer.Host.Contains("localhost"))
    13.  
      {
    14.  
      // 获取文件服务器端物理路径
    15.  
      string FileName = context.Server.MapPath(context.Request.FilePath);
    16.  
      context.Response.ContentType = "image/JPEG";
    17.  
      context.Response.WriteFile(FileName);
    18.  
      }
    19.  
      else
    20.  
      {
    21.  
      context.Response.ContentType = "image/JPEG";
    22.  
      context.Response.WriteFile("/Content/Image/Forbidden.jpg");
    23.  
      }
    24.  
      }
    25.  
      }

    解释一下,如果请求上下文的UrlReferrer或者Host都是null,那么返回一个404的图片,如果请求上下文的UrlReferrer或者Host不是null,但host不是我们自己的网站(这里因为是本地调试,所以网址是localhost),同样返回一个404的图片。

    我们比较一下,先监控一下能获得正常图片的请求:

    再监控一下不能正常访问,只显示404图片:

    当然,Http请求是可以模拟的,只要模拟的到位,一样可以得到正确的图片。

    二. Webform请求的HttpApplication众多事件流程图

    三.HttpModule和HttpHandler的区别

    HttpModule:是任何一个Http请求都必须执行的东西,是附着在事件(Event)上的动作。

    HttpHandler:任何一个请求一定有一个HttpHandler在处理,这个HttpHandler要么是aspx,要么是ashx,要么是mvc。

    那么,什么场景用HttpModule,什么场景用HttpHandler?

    1.session处理 : HttpModule

    2.身份认证:HttpModule

    3.权限检测:HttpModule

    4.trace.axd查看追踪信息:HttpHandler

    5.Outputcach输出缓存:HttpModule

    6.config禁止下载:HttpHandler

    7.cs代码不允许访问:HttpHandler

    HttpModule适合处理全局的,因为任何请求都要经过它,任何请求都需要session,都需要身份认证,都需要权限检测,都需要缓存处理。

    HttpHandler适合处理单一请求,查看追踪信息,config禁止下载,cs代码不允许访问这些都属于单一请求。

    其实所有的东西HttpModule都可以做到,只是不适合而已。

    四.路由、HttpHandler映射,哪个先执行?

    用上面的,verify的例子,http://localhost:8090/handler/1.verify ,我们先在web.config中做了映射,所以它可以执行我们自定义的HttpHandler,输出显示验证码的图片。

    如果url改成 http://localhost:8090/1.verify呢,找不到控制器。

    这个图说明,虽然我们给verify做了映射,但是路由在HttpHandler之前就执行了,即还没有到MapRequestHandler,就被拦截了,谁拦截的?PostResolveRequestCache。

    怎么做到的?要从UrlRoutingModule说起,用反编译工具打开UrlRoutingModule

    再看一下PostResolveRequestCache方法里面干了什么。

    那么MapRoute又是什么呢?用反编译工具看:

    回到刚才的 PostResolveRequestCache方法。

    RemapHandle是干什么的呢?解释一下 

    五.MVC路由以及和Webform的区别

    那为什么aspx可以顺序执行下去,而MVC跳过去了呢?看看上面说到的GetRouteData方法,就是在这个方法里面,webform和mvc产生了分支。

    再看一个MVC总的流程图:

    B2:用MapRoute来增加路由。

    并且把route放入RouteCollection中。route是什么?route的构造函数,参数分别是url和MvcRouteHandler,这里讲到B3了。

    MvcRouteHandler里面又是什么?

    B4:MvcRouteHandler可以通过GetHttpHandler方法得到一个HttpHandler,所以也可以说MvcRouteHandler负责生产IHttpHandler,如果不好理解,可以把MvcRouteHandler看成是HttpHandler。所以route的构造函数,就是传入了一个url和一个处理这个url的HttpHandler。这就和我们在webconfig文件中自定义的HttpHandler映射是一个道理,那里是什么后缀对应什么HttpHandler来处理(webform),这里是什么url对应什么HttpHandler来处理(mvc)。

    url和处理这个url的HttpHandler,它们二者的对应关系是怎么对应的?就是在RouteConfig中建立的:

    B5:所以RouteCollection里面有很多这样的route。

    现在可以宏观的看这张mvc流程图了,先启动网站A1,然后进入Application_start(B1),执行Global(B2)中的RouteConfig,用routes.MapRoute注册了很多route,这些route保存了url和处理这些url的MvcRouteHandler(B3),然后这些MvcRouteHandler生产出HttpHandler(B4),将这些route放入RouteCollection(B5),好了 ,路由规则做好了,进入A2,22个事件依次执行(A3),执行到PostResolveRequestCache的时候,扩展了一个UrlRoutingModule(A4),UrlRoutingModule拿着url去在B5中已经准备好了的RouteCollection中去做匹配,找处理该url的MvcRouteHandler(A5),找到了MvcRouteHandler,然后把这个MvcRouteHandler生产的HttpHandler(mvc中就是MvcHandler)给context。

    回头再看看PostResolveRequestCache方法:

  • 相关阅读:
    java学习——abstract 和 final
    apache配置访问目录的默认页面
    Beyond Compare 4
    idea常用插件
    linux关闭防火墙
    本地项目上传到gitlab
    删除数据库中多余的数据
    git上传本地项目到gitlab
    谷歌浏览器插件
    域名
  • 原文地址:https://www.cnblogs.com/zcbk/p/12190485.html
Copyright © 2020-2023  润新知