一. 自定義擴展名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 }
②. 在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>
③. 因爲自己框架自己已經有一套路由規則用來處理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 }
②. 在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>
4. 代碼測試
新建一個Index頁面,在該頁面經過img標籤直接連接到圖片地址,顯示圖片,而後將該項目發佈到測試服務器上。
①:訪問地址:http://121.42.200.127:8099/Pipe/Index, 正常顯示該頁面中的圖片, 表示該圖片請求爲站內正常的請求
②:訪問地址:http://121.42.200.127:8099/Content/imageHandle/pipe1.jpg, 不能正常訪問,表示該圖片請求爲盜鏈