第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)
一. 自定义扩展名
1. 前言
凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET Framework才调用HttpHandler的ProcessRequest方法来对这个HTTP请求进行真正的处理,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
2. 背景
我们在日常开发中,也许会碰到一些这样的特殊需求,在路由规则之外,想给自己预留一个后门,进行一些小动作;或者想自定义一种特有的看起来很酷炫的后缀;或者默写后缀不想走MVC框架默认提供的处理流程,那么使用HttpHander进行扩展,再合适不过。
下面我们先扩展一个后缀为 .ypf的处理请求,凡是该后缀的请求,统一显示验证码页面。
3. 详细步骤
①. 新建一个类(ypfCode),实现IHttpHandler接口。
/// <summary>
///这里自定义的handle为一般处理程序,实现了IHttpHandler接口
///IRequiresSessionState是为了使http请求具有会话状态的读写权限,即能操控: context.Session["CheckCode"] = code;
/// </summary>
public class ypfCode : IHttpHandler, IRequiresSessionState
{
/// <summary>
/// 您将需要在网站的 Web.config 文件中配置此处理程序
/// 并向 IIS 注册它,然后才能使用它。有关详细信息,
/// 请参阅以下链接: https://go.microsoft.com/?linkid=8101007
/// </summary>
#region IHttpHandler Members public bool IsReusable
{
// 如果无法为其他请求重用托管处理程序,则返回 false。
// 如果按请求保留某些状态信息,则通常这将为 false。
get { return true; }
} public void ProcessRequest(HttpContext context)
{
//在此处写入您的处理程序实现。
string code = "";
Bitmap bitmap = VerifyCodeHelper.CreateVerifyCode(out code);
context.Session["CheckCode"] = code;
bitmap.Save(context.Response.OutputStream, ImageFormat.Gif);
context.Response.ContentType = "image/gif";
}
#endregion
}
补充一个验证码实现类:
public class VerifyCodeHelper
{
public static Bitmap CreateVerifyCode(out string code)
{
//建立Bitmap对象,绘图
Bitmap bitmap = new Bitmap(, );
Graphics graph = Graphics.FromImage(bitmap);
graph.FillRectangle(new SolidBrush(Color.White), , , , );
Font font = new Font(FontFamily.GenericSerif, , FontStyle.Bold, GraphicsUnit.Pixel);
Random r = new Random();
string letters = "ABCDEFGHIJKLMNPQRSTUVWXYZ0123456789"; StringBuilder sb = new StringBuilder(); //添加随机的五个字母
for (int x = ; x < ; x++)
{
string letter = letters.Substring(r.Next(, letters.Length - ), );
sb.Append(letter);
graph.DrawString(letter, font, new SolidBrush(Color.Black), x * , r.Next(, ));
}
code = sb.ToString(); //混淆背景
Pen linePen = new Pen(new SolidBrush(Color.Black), );
for (int x = ; x < ; x++)
graph.DrawLine(linePen, new Point(r.Next(, ), r.Next(, )), new Point(r.Next(, ), r.Next(, )));
return bitmap;
}
}
②. 在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:表示该类所在库的程序集名称
<!--VS2013及以后/IIS7.0之后的集成模式 需要添加下面的system.webServer节点-->
<system.webServer> <!--. 在此处配置modules-->
<modules runAllManagedModulesForAllRequests="false">
<!--1.1 runAllManagedModulesForAllRequests处理静态文件的请求-->
<remove name="FormsAuthentication" />
<!--1.2 优化网站性能,去掉不需要的module-->
<remove name="RoleManager" />
<remove name="FileAuthorization" />
<remove name="UrlAuthorization" />
</modules>
<!--. 在此处配置handlers-->
<handlers>
<!--2.1 优化网站性能,去掉不需要的module-->
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <!--2.2 添加自定义handlers-->
<!--2.2. 后缀为ypf的请求 -->
<add name="ypf" path="*.ypf" verb="*" type="Ypf.Web.Core.PipeLine.ypfCode,Ypf.Web.Core" /> <!--2.2. 图片处理请求 -->
<!--方案一 逐个添加不同格式的图片 特别注意:不支持在一个path写多个扩展名-->
<!--<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" />-->
<!--方案二 通过HangerFactory来处理 特别注意:不支持在一个path写多个扩展名 -->
<add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
<add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
<add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" /> </handlers>
</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接口
/// <summary>
/// 图片防盗链
/// 该自定义handle用来处理各种获取图片的请求
/// (这里处理 jpg gif png三种格式的图片)
/// </summary>
public class imgHandle : IHttpHandler
{ public bool IsReusable
{
// 如果无法为其他请求重用托管处理程序,则返回 false。
// 如果按请求保留某些状态信息,则通常这将为 false。
get { return true; }
} public void ProcessRequest(HttpContext context)
{ //0.获取图片的返回类型
string type = GetContentType(context.Request.Url.ToString()); var beforeUrl = context.Request.ServerVariables["HTTP_REFERER"]; //1. 如果请求的url为空,或者请求的主机部分为空,返回一张禁止倒链的图片
if (context.Request.UrlReferrer == null || context.Request.UrlReferrer.Host == null)
{
//context.Response.ContentType = "image/JPEG";
//context.Response.WriteFile("/Content/imageHandle/Forbidden.jpg"); context.Response.Write("您的请求是非法,请勿再试");
}
else
{
//2. url不空,且包含自己主机域名,表示为自己网站的请求,显示正常图片
//正常发布的时候这里用域名或者ip,localhost为了本地调试
if (context.Request.UrlReferrer.Host.Contains("121.42.200.127"))
{
string FileName = context.Server.MapPath(context.Request.FilePath);
context.Response.ContentType = type;
context.Response.WriteFile(FileName);
}
else
{
//3. url不空,但不包含自己主机域名,表示该请求为盗链请求,返回一张禁止倒链的图片
//context.Response.ContentType = "image/JPEG";
//context.Response.WriteFile("/Content/imageHandle/Forbidden.jpg"); context.Response.Write("您的请求是非法,请勿再试");
} }
} /// <summary>
/// 将地址转换成图片返回值
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private static string GetContentType(string url)
{
switch (Path.GetExtension(url))
{
case ".gif":
return "Image/gif";
case ".jpg":
return "Image/jpeg";
case ".png":
return "Image/png";
default:
break;
}
return null;
} }
扩展:也可以自定义handleFactory,实现IHttpHandlerFactory接口,在handleFactory中指定不同hander。
/// <summary>
/// 自定义的一个HandleFactory,用来指定不同的后缀调用不同的Handle
/// 这里是一个ImageHandlerFactory,处理不同 图片后缀
/// </summary>
public class ImageHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
string path = context.Request.PhysicalPath;
if (Path.GetExtension(path).Equals(".jpg"))
{
return new imgHandle();
}
else if (Path.GetExtension(path).Equals(".png"))
{
return new imgHandle();
}
else
{
//这里可以继续扩展,这里测试不继续扩展了
return new imgHandle();
} } public void ReleaseHandler(IHttpHandler handler)
{ }
}
②. 在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" />
<!--VS2013及以后/IIS7.0之后的集成模式 需要添加下面的system.webServer节点-->
<system.webServer> <!--. 在此处配置modules-->
<modules runAllManagedModulesForAllRequests="false">
<!--1.1 runAllManagedModulesForAllRequests处理静态文件的请求-->
<remove name="FormsAuthentication" />
<!--1.2 优化网站性能,去掉不需要的module-->
<remove name="RoleManager" />
<remove name="FileAuthorization" />
<remove name="UrlAuthorization" />
</modules>
<!--. 在此处配置handlers-->
<handlers>
<!--2.1 优化网站性能,去掉不需要的module-->
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <!--2.2 添加自定义handlers-->
<!--2.2. 后缀为ypf的请求 -->
<add name="ypf" path="*.ypf" verb="*" type="Ypf.Web.Core.PipeLine.ypfCode,Ypf.Web.Core" /> <!--2.2. 图片处理请求 -->
<!--方案一 逐个添加不同格式的图片 特别注意:不支持在一个path写多个扩展名-->
<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" />
<!--方案二 通过HangerFactory来处理 特别注意:不支持在一个path写多个扩展名 -->
<!--<add name="img" path="*.jpg" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
<add name="png" path="*.png" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />
<add name="gif" path="*.gif" verb="*" type="Ypf.Web.Core.PipeLine.ImageHandlerFactory,Ypf.Web.Core" />--> </handlers>
</system.webServer>
4. 代码测试
新建一个Index页面,在该页面通过img标签直接链接到图片地址,显示图片,然后将该项目发布到测试服务器上。

①:访问地址:http://121.42.200.127:8099/Pipe/Index, 正常显示该页面中的图片, 表示该图片请求为站内正常的请求
②:访问地址:http://121.42.200.127:8099/Content/imageHandle/pipe1.jpg, 不能正常访问,表示该图片请求为盗链

第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)的更多相关文章
- Asp.Net Core 通过自定义中间件防止图片盗链的实例(转)
一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或 ...
- JavaWeb -- 自定义标签实例, 防盗链, JSTL 核心标签
1. 自定义标签应用实例1: 防盗链 标签处理类 public class RefererTag extends SimpleTagSupport { private String site; pri ...
- SpringCloud微服务实战——搭建企业级开发框架(二十六):自定义扩展OAuth2实现短信验证码登录
现在手机验证码登录似乎是每个网站必备的功能,OAuth2支持扩展自定义授权模式,前面介绍了如何在系统集成短信通知服务,这里我们进行OAuth2的授权模式自定义扩展,使系统支持短信验证码登录. 1.在g ...
- centos LB负载均衡集群 三种模式区别 LVS/NAT 配置 LVS/DR 配置 LVS/DR + keepalived配置 nginx ip_hash 实现长连接 LVS是四层LB 注意down掉网卡的方法 nginx效率没有LVS高 ipvsadm命令集 测试LVS方法 第三十三节课
centos LB负载均衡集群 三种模式区别 LVS/NAT 配置 LVS/DR 配置 LVS/DR + keepalived配置 nginx ip_hash 实现长连接 LVS是四层LB ...
- centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符 通配符 特殊符号. * + ? 总结 问加星 cat -n nl 输出文件内容并加上行号 alias放~/.bash_profile 2015-4-10 第十三节课
centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符 通配符 特殊符号. * + ? 总结 问加星 cat -n nl 输出文件内容并加上行号 alias放~ ...
- SharePoint 2013 自定义扩展菜单(二)
接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomA ...
- 第三百一十三节,Django框架,Session
第三百一十三节,Django框架,Session Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 1.数据库(默认)2.缓存3.文件4.缓存+数据库5.加密c ...
- centos LNMP第一部分环境搭建 LAMP LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/php/{p.conf.default,p.conf} php运行方式SAPI介绍 第二十三节课
centos LNMP第一部分环境搭建 LAMP安装先后顺序 LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/local/php/{ ...
- (转)第二十三节 inotify事件监控工具
第二十三节 inotify事件监控工具 标签(空格分隔): Linux实战教学笔记-陈思齐 原文:http://www.cnblogs.com/chensiqiqi/p/6542268.html 第1 ...
随机推荐
- JavaScript -- 原型:prototype的使用
JavaScript -- 原型:prototype的使用 在 JavaScript 中,prototype 是函数的一个属性,同时也是由构造函数创建的对象的一个属性. 函数的原型为对象. 它主要在函 ...
- swoole多端口监听
今天测试swoole写webserver实现多端口监听.记录下爬过的坑:关于tcp协议监听触发不到receive!!!!! 首先上服务端代码 class Http { /** * 服务实例 * @va ...
- web Deploy发布问题
使用vs开发的时候,经常会发布项目.传统发布是登陆远程桌面.或ftp这些发布都有一定的麻烦.不能灵活的管理发布的文件.因此后来研究了web Deploy,研究之后发现是很不错的发布工具.这里把我使用w ...
- linux服务器硬盘IO读写负载高来源定位 pt-ioprofile
首先 .用top命令查看 1 2 3 4 5 top - 16:15:05 up 6 days, 6:25, 2 users, load average: 1.45, 1.77, 2.14 ...
- 需求规格说明书(SRS)特点
需求说明书的7大特征: 完整性 正确性 可行性 必要性 划分优先级 无二义性 可验证性 每条需求规格说明书的4大特点: 完整性 一致性 可修改性 可跟踪性 需求管理就是一种获取.组织并记录系统需求的系 ...
- Windows服务器环境下jenkins下载和安装
1.下载jenkins 在windows系统上搭建jenkins持续集成有两种方法:1.war文件,可以用tomcat或者java命令直接运行2.msi安装,作为系统服务后台运行 下载地址 https ...
- 微信小程序测试
1.连接真机,微信已经登录过了 2.代码: 3.appium自带的识别工具 4.设置工具连接设备的方式 参考资料: https://www.cnblogs.com/yoyoketang/p/91449 ...
- Golang 入门系列(十一)Go语言实现webapi
之前,已经讲过很多Golang的东西,比如基础语法,mysql的使用,redis的使用等等,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/ca ...
- SpringBoot整合RabbitMQ-消息可靠性投递
本系列是学习SpringBoot整合RabbitMQ的练手,包含服务安装,RabbitMQ整合SpringBoot2.x,消息可靠性投递实现等三篇博客. 学习路径:https://www.imooc. ...
- 基于C#的钉钉SDK开发(1)--对官方SDK的重构优化
在前段时间,接触一个很喜欢钉钉并且已在内部场景广泛使用钉钉进行工厂内部管理的客户,如钉钉考勤.日常审批.钉钉投影.钉钉门禁等等方面,才体会到原来钉钉已经已经在企业上可以用的很广泛的,因此回过头来学习研 ...