一. 自定义扩展名

1. 前言

  凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET Framework才调用HttpHandler的ProcessRequest方法来对这个HTTP请求进行真正的处理,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。

2. 背景

  我们在日常开发中,也许会碰到一些这样的特殊需求,在路由规则之外,想给自己预留一个后门,进行一些小动作;或者想自定义一种特有的看起来很酷炫的后缀;或者默写后缀不想走MVC框架默认提供的处理流程,那么使用HttpHander进行扩展,再合适不过。

  下面我们先扩展一个后缀为 .ypf的处理请求,凡是该后缀的请求,统一显示验证码页面。

3. 详细步骤

  ①. 新建一个类(ypfCode),实现IHttpHandler接口。

 1  /// <summary>
 2     ///这里自定义的handle为一般处理程序,实现了IHttpHandler接口
 3     ///IRequiresSessionState是为了使http请求具有会话状态的读写权限,即能操控: context.Session["CheckCode"] = code;
 4     /// </summary>
 5     public class ypfCode : IHttpHandler, IRequiresSessionState
 6     {
 7         /// <summary>
 8         /// 您将需要在网站的 Web.config 文件中配置此处理程序
 9         /// 并向 IIS 注册它,然后才能使用它。有关详细信息,
10         /// 请参阅以下链接: https://go.microsoft.com/?linkid=8101007
11         /// </summary>
12         #region IHttpHandler Members
13
14         public bool IsReusable
15         {
16             // 如果无法为其他请求重用托管处理程序,则返回 false。
17             // 如果按请求保留某些状态信息,则通常这将为 false。
18             get { return true; }
19         }
20
21         public void ProcessRequest(HttpContext context)
22         {
23             //在此处写入您的处理程序实现。
24             string code = "";
25             Bitmap bitmap = VerifyCodeHelper.CreateVerifyCode(out code);
26             context.Session["CheckCode"] = code;
27             bitmap.Save(context.Response.OutputStream, ImageFormat.Gif);
28             context.Response.ContentType = "image/gif";
29         }
30         #endregion
31     }

  补充一个验证码实现类:

 1  public class VerifyCodeHelper
 2     {
 3         public static Bitmap CreateVerifyCode(out string code)
 4         {
 5             //建立Bitmap对象,绘图
 6             Bitmap bitmap = new Bitmap(200, 60);
 7             Graphics graph = Graphics.FromImage(bitmap);
 8             graph.FillRectangle(new SolidBrush(Color.White), 0, 0, 200, 60);
 9             Font font = new Font(FontFamily.GenericSerif, 48, FontStyle.Bold, GraphicsUnit.Pixel);
10             Random r = new Random();
11             string letters = "ABCDEFGHIJKLMNPQRSTUVWXYZ0123456789";
12
13             StringBuilder sb = new StringBuilder();
14
15             //添加随机的五个字母
16             for (int x = 0; x < 5; x++)
17             {
18                 string letter = letters.Substring(r.Next(0, letters.Length - 1), 1);
19                 sb.Append(letter);
20                 graph.DrawString(letter, font, new SolidBrush(Color.Black), x * 38, r.Next(0, 15));
21             }
22             code = sb.ToString();
23
24             //混淆背景
25             Pen linePen = new Pen(new SolidBrush(Color.Black), 2);
26             for (int x = 0; x < 6; x++)
27                 graph.DrawLine(linePen, new Point(r.Next(0, 199), r.Next(0, 59)), new Point(r.Next(0, 199), r.Next(0, 59)));
28             return bitmap;
29         }
30     } 

View Code

  ②. 在Web.config文件中的 <system.webServer>→<handlers>下添加以下节点,表示以.ypf为后缀的请求统一由ypfCode处理,其中

  <add name="ypf" path="*.ypf" verb="*" type="Ypf.Web.Core.PipeLine.ypfCode,Ypf.Web.Core" />

    Ypf.Web.Core.PipeLine.ypfCode:表示该类的命名空间

    Ypf.Web.Core:表示该类所在库的程序集名称

 1  <!--VS2013及以后/IIS7.0之后的集成模式  需要添加下面的system.webServer节点-->
 2   <system.webServer>
 3
 4     <!--1. 在此处配置modules-->
 5     <modules runAllManagedModulesForAllRequests="false">
 6       <!--1.1 runAllManagedModulesForAllRequests处理静态文件的请求-->
 7       <remove name="FormsAuthentication" />
 8       <!--1.2 优化网站性能,去掉不需要的module-->
 9       <remove name="RoleManager" />
10       <remove name="FileAuthorization" />
11       <remove name="UrlAuthorization" />
12     </modules>
13     <!--2. 在此处配置handlers-->
14     <handlers>
15       <!--2.1 优化网站性能,去掉不需要的module-->
16       <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
17       <remove name="OPTIONSVerbHandler" />
18       <remove name="TRACEVerbHandler" />
19       <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
20
21       <!--2.2 添加自定义handlers-->
22       <!--2.2.1 后缀为ypf的请求 -->
23       <add name="ypf" path="*.ypf" verb="*" type="Ypf.Web.Core.PipeLine.ypfCode,Ypf.Web.Core" />
24
25       <!--2.2.2 图片处理请求 -->
26       <!--方案一 逐个添加不同格式的图片   特别注意:不支持在一个path写多个扩展名-->
27       <!--<add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />
28       <add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />
29       <add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />-->
30       <!--方案二 通过HangerFactory来处理  特别注意:不支持在一个path写多个扩展名 -->
31       <add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
32       <add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
33       <add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
34
35     </handlers>
36   </system.webServer>

View Code

  ③. 由于本身框架本身已经有一套路由规则用来处理http请求,所以需要在RouteConfig中忽略该自定义Handle的规则,如下:

  routes.IgnoreRoute("MyTest/{*pathInfo}"); 表示MyTest/格式的请求不进行路由验证

  

  ④. 测试:http://localhost:7559/MyTest/xxx.ypf 均返回验证码图片

二. 图片防盗链

1. 什么是图片防盗链

  自己网站中展示的自己的图片通常是放在自己服务器上,很多无耻的网站获取到别人网站的图片地址,放到自己网站上,这就是图片盗链。

图片被盗链损耗的是自己服务器的流量。

2. 防盗链的代码实现原理

当接受到一张图片请求的时候

1. 判断该图片请求是从哪一个请求连接过来的(或者从哪一个页面连接过来的),如果为空,表示是一个单独的图片请求,肯定不该站内的,

所以判断为盗链。两种判断方式如下

  a: context.Request.ServerVariables["HTTP_REFERER"]

  b: context.Request.UrlReferrer

2. 如果上一个请求不为空,则判断上一个请求中是否含有该站的域名或ip地址,如果没有,则为非法请求,不是该站内的请求,

所以判断为盗链。两种判断方法

  a:context.Request.UrlReferrer.Host.Contains("121.42.223.23")

  b:context.Request.ServerVariables["HTTP_REFERER"].Contains("121.42.223.23")

3. 自定义hander进行处理

①. 自定义imgHandle,实现IHttpHandler接口

 1 /// <summary>
 2     /// 图片防盗链
 3     ///  该自定义handle用来处理各种获取图片的请求
 4     /// (这里处理 jpg gif png三种格式的图片)
 5     /// </summary>
 6     public class imgHandle : IHttpHandler
 7     {
 8
 9         public bool IsReusable
10         {
11             // 如果无法为其他请求重用托管处理程序,则返回 false。
12             // 如果按请求保留某些状态信息,则通常这将为 false。
13             get { return true; }
14         }
15
16         public void ProcessRequest(HttpContext context)
17         {
18
19             //0.获取图片的返回类型
20             string type = GetContentType(context.Request.Url.ToString());
21
22             var beforeUrl = context.Request.ServerVariables["HTTP_REFERER"];
23
24             //1. 如果请求的url为空,或者请求的主机部分为空,返回一张禁止倒链的图片
25             if (context.Request.UrlReferrer == null || context.Request.UrlReferrer.Host == null)
26             {
27                 //context.Response.ContentType = "image/JPEG";
28                 //context.Response.WriteFile("/Content/imageHandle/Forbidden.jpg");
29
30                 context.Response.Write("您的请求是非法,请勿再试");
31             }
32             else
33             {
34                 //2. url不空,且包含自己主机域名,表示为自己网站的请求,显示正常图片
35                 //正常发布的时候这里用域名或者ip,localhost为了本地调试
36                 if (context.Request.UrlReferrer.Host.Contains("121.42.200.127"))
37                 {
38                     string FileName = context.Server.MapPath(context.Request.FilePath);
39                     context.Response.ContentType = type;
40                     context.Response.WriteFile(FileName);
41                 }
42                 else
43                 {
44                     //3. url不空,但不包含自己主机域名,表示该请求为盗链请求,返回一张禁止倒链的图片
45                     //context.Response.ContentType = "image/JPEG";
46                     //context.Response.WriteFile("/Content/imageHandle/Forbidden.jpg");
47
48                     context.Response.Write("您的请求是非法,请勿再试");
49                 }
50
51             }
52         }
53
54         /// <summary>
55         /// 将地址转换成图片返回值
56         /// </summary>
57         /// <param name="url"></param>
58         /// <returns></returns>
59         private static string GetContentType(string url)
60         {
61             switch (Path.GetExtension(url))
62             {
63                 case ".gif":
64                     return "Image/gif";
65                 case ".jpg":
66                     return "Image/jpeg";
67                 case ".png":
68                     return "Image/png";
69                 default:
70                     break;
71             }
72             return null;
73         }
74
75     }

  扩展:也可以自定义handleFactory,实现IHttpHandlerFactory接口,在handleFactory中指定不同hander。

 1 /// <summary>
 2     /// 自定义的一个HandleFactory,用来指定不同的后缀调用不同的Handle
 3     /// 这里是一个ImageHandlerFactory,处理不同 图片后缀
 4     /// </summary>
 5     public class ImageHandlerFactory : IHttpHandlerFactory
 6     {
 7         public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
 8         {
 9             string path = context.Request.PhysicalPath;
10             if (Path.GetExtension(path).Equals(".jpg"))
11             {
12                 return new imgHandle();
13             }
14             else if (Path.GetExtension(path).Equals(".png"))
15             {
16                 return new imgHandle();
17             }
18             else
19             {
20                 //这里可以继续扩展,这里测试不继续扩展了
21                 return new imgHandle();
22             }
23
24         }
25
26         public void ReleaseHandler(IHttpHandler handler)
27         {
28
29         }
30     }

View Code

②. 在Web.config文件中的 <system.webServer>→<handlers>下添加:

<add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />

<add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />

<add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />

 1  <!--VS2013及以后/IIS7.0之后的集成模式  需要添加下面的system.webServer节点-->
 2   <system.webServer>
 3
 4     <!--1. 在此处配置modules-->
 5     <modules runAllManagedModulesForAllRequests="false">
 6       <!--1.1 runAllManagedModulesForAllRequests处理静态文件的请求-->
 7       <remove name="FormsAuthentication" />
 8       <!--1.2 优化网站性能,去掉不需要的module-->
 9       <remove name="RoleManager" />
10       <remove name="FileAuthorization" />
11       <remove name="UrlAuthorization" />
12     </modules>
13     <!--2. 在此处配置handlers-->
14     <handlers>
15       <!--2.1 优化网站性能,去掉不需要的module-->
16       <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
17       <remove name="OPTIONSVerbHandler" />
18       <remove name="TRACEVerbHandler" />
19       <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
20
21       <!--2.2 添加自定义handlers-->
22       <!--2.2.1 后缀为ypf的请求 -->
23       <add name="ypf" path="*.ypf" verb="*" type="Ypf.Web.Core.PipeLine.ypfCode,Ypf.Web.Core" />
24
25       <!--2.2.2 图片处理请求 -->
26       <!--方案一 逐个添加不同格式的图片   特别注意:不支持在一个path写多个扩展名-->
27       <add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />
28       <add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />
29       <add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.imgHandle,Ypf.Web.Core" />
30       <!--方案二 通过HangerFactory来处理  特别注意:不支持在一个path写多个扩展名 -->
31       <!--<add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
32       <add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
33       <add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />-->
34
35     </handlers>
36   </system.webServer>

View Code

4. 代码测试

  新建一个Index页面,在该页面通过img标签直接链接到图片地址,显示图片,然后将该项目发布到测试服务器上。

①:访问地址:http://121.42.200.127:8099/Pipe/Index, 正常显示该页面中的图片, 表示该图片请求为站内正常的请求

②:访问地址:http://121.42.200.127:8099/Content/imageHandle/pipe1.jpg, 不能正常访问,表示该图片请求为盗链

转载于:https://www.cnblogs.com/yaopengfei/p/8037255.html

第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)相关推荐

  1. 环信3.0自定义扩展消息

    最近公司项目需要用到环信,早就听说过环信文档写的比较坑,继承过后才发现哪里是坑,简直是无底洞... 项目需求是这样的,菜单中有一个房源按钮,点击后弹出房源信息列表,点击列表中的Item将此条Item的 ...

  2. 使用C#为.NET Interactive开发自定义扩展

    在前面的文章中,我们介绍了如何在.NET Interactive notebook绘制图表和执行SQL. 那么,能不能为.NET Interactive开发交互功能呢? 今天,我们就来演示如何实现. ...

  3. uni-app.08.自定义扩展图标

    uni-app自定义扩展图标 前言 自定义扩展图标 1.阿里矢量图标库 2.搜索图标 3.添加至项目 4.下载至本地 5.解压重命名 6.项目中引入 1).将adminIconfont拷贝至stati ...

  4. SharePoint 2013 自定义扩展菜单(二)

    转载自:http://www.cnblogs.com/jianyus/p/3376075.html 包含另外三个例子,列表设置.管理中心.人员和组添加菜单 接博文<SharePoint 2013 ...

  5. VS Code 安装 Go 插件、自定义扩展配置、断点调试

    1. 安装插件 使用快捷键 Ctrl+Shift+X 打开插件安装页面,安装 Go 插件. 2. 自定义扩展配置 使用快捷键 Ctrl+, 打开自定义配置页,编辑 settings.json ,定义与 ...

  6. 2021年大数据Hadoop(二十二):MapReduce的自定义分组

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 MapReduce的自定义分组 需求 分析 实现 第一步: ...

  7. Python编程基础:第五十三节 匿名函数Lambda Function

    第五十三节 匿名函数Lambda Function 前言 实践 前言 匿名函数是一种非常优雅的表达方式,它可以将函数定义用一行代码进行表示.其书写方式为参数列表:函数实现,其中多个参数之间用逗号隔开, ...

  8. Python编程基础:第四十三节 多继承Multiple Inheritance

    第四十三节 多继承Multiple Inheritance 前言 实践 前言 多继承是指一个子类可以拥有多个父类,其所有父类的属性和方法都能被其调用.其中多个父类之间用逗号隔开. 实践 我们先定义两个 ...

  9. Python编程基础:第三十三节 文件复制Copy a File

    第三十三节 文件复制Copy a File 前言 实践 前言 当我们需要将一个文件中的内容复制到另一个文件中时,就需要用到copyfile()函数,该函数一共有两个参数copyfile(src, ds ...

最新文章

  1. php manager如何安装目录,宝塔面板安装OneManager-php – Onedrive的列表索引和管理程序...
  2. android 使用xml定义自己的View
  3. 让思考成为一种习惯:一位软件工程专业学生的大学生涯规划
  4. android网络通信之HTTP协议教程实例汇总
  5. linux mysql v_Linux 主机升级MySQL v5.5 性能提升360%
  6. 在VS2015中用C++创建DLL并用C#调用且同时实现对DLL的调试
  7. 产品人如何在小企业中夹缝生存?
  8. java serializeutils_java序列化 SerializeUtil
  9. VBA合并csv文件
  10. 普通Java类获取Spring的bean
  11. 使用TestNG-xslt美化测试报告
  12. java 空文件夹删除_java创建文件文件夹,删除空文件夹,删除文件夹以及所有文件...
  13. 科三十六项操作方法指导
  14. GROW GM65 条码二维码扫描识别模块 兼容大部分条码和二维码
  15. 计算机外联管理办法,外联部管理制度
  16. html标签不使用css样式,html – 忽略CSS样式
  17. 联想拯救者电脑高清壁纸
  18. gridcontrol 添加行删除行
  19. Show出你的高超技能 首届“中国高性能云计算创新大赛”要开赛啦!
  20. windows客户端通过脚本文件添加信任站点

热门文章

  1. 通过filebeat、logstash、rsyslog采集nginx日志的几种方式
  2. 什么是「数独」,简单介绍
  3. 无法连接Elasticsearch解决方案
  4. open_basedir restriction in effect,解决php引入文件权限问题
  5. 解决idea中maven plugins标红的问题
  6. SpringMVC中404错误解决方法总结
  7. mybatis项目报错:java.sql.SQLException: ORA-00911: 无效字符 解决方法
  8. 为什么要使用Ruby的attr_accessor,attr_reader和attr_writer?
  9. XmlHttpRequest错误:Access-Control-Allow-Origin不允许使用原点null
  10. Tab键== 4个空格并在Vim中的花括号后自动缩进