第十三節:HttpHander擴展及應用(自定義擴展名、圖片防盜鏈)

一. 自定義擴展名web

1. 前言服務器

   凡是實現了IHttpHandler接口的類均爲Handler類,HttpHandler是一個HTTP請求的真正處理中心,在HttpHandler容器中,ASP.NET Framework才調用HttpHandler的ProcessRequest方法來對這個HTTP請求進行真正的處理,真正地對客戶端請求的服務器頁面作出編譯和執行,並將處理事後的信息附加在HTTP請求信息流中再次返回到HttpModule中。框架

2. 背景less

   咱們在平常開發中,也許會碰到一些這樣的特殊需求,在路由規則以外,想給本身預留一個後門,進行一些小動做;或者想自定義一種特有的看起來很酷炫的後綴;或者默寫後綴不想走MVC框架默認提供的處理流程,那麼使用HttpHander進行擴展,再合適不過。dom

   下面咱們先擴展一個後綴爲 .ypf的處理請求,凡是該後綴的請求,統一顯示驗證碼頁面。ide

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, 不能正常訪問,表示該圖片請求爲盜鏈

 

 

相關文章
相關標籤/搜索