IHttphandler之防止图片盗链
同样IHttpHandler原理见“IHttphandler子Url重写”一文。
web.config设置如下:
<httpHandlers>
<add verb="*" path="*.gif" type="MyHttpHandler.PreventAntiLeechHandler,MyHttpHandler"/> </httpHandlers>
如果请求的路径为gif图片(*.gif)则经过MyHttpHandler.PreventAntiLeechHandler处理后返回。
PreventAntiLeechHandler实现如下:
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Drawing;
using System.IO;
namespace MyHttpHandler
{
class PreventAntiLeechHandler : IHttpHandler
{
#region IHttpHandler 成员
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
if (context.Request.Url.Authority == context.Request.UrlReferrer.Authority)
{
CommonDeal.DealImageRequest(context);
}
else
{
CommonDeal.ReturnErrorImage(context);
}
}
#endregion
}
}
CommonDeal实现如下:
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
namespace MyHttpHandler
{
internal class CommonDeal
{
public static void DealImageRequest(HttpContext context)
{
Font titleFont = new Font("黑体", 12, FontStyle.Bold);//标题字体
Font font = new Font("Consolas", 8, FontStyle.Regular);//数字0字有斜线的字体:WST_Ital, 01 DigitGraphics , 00 Starmap Truetype,Consolas,
//Font font = new Font("WST_Engl", 8);//正文字体
Font headerFont = new Font("黑体", 12, FontStyle.Bold);//列名标题
Font footerFont = new Font("Arial", 8);//页脚显示页数的字体
Font upLineFont = new Font("Arial", 9, FontStyle.Bold);//当header分两行显示的时候,上行显示的字体。
Font underLineFont = new Font("Arial", 8);//当header分两行显示的时候,下行显示的字
Font enFont = new Font("Times New Roman", 12);
MemoryStream ms = new MemoryStream();
string filePath = context.Server.MapPath("Image" + context.Request.Path);
try
{
Image image = Image.FromFile(filePath);
if (IsPixelFormatIndexed(image.PixelFormat))
{
Bitmap bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
using (Graphics graphic = Graphics.FromImage(bmp))
{
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphic.DrawImage(image, 0, 0);
graphic.DrawString("pangxiaoliang", enFont, new SolidBrush(Color.LightGray), 2, 2);
graphic.DrawString("pangxiaoliang", enFont, new SolidBrush(Color.Black), 0, 0);
}
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
bmp.Dispose();
}
else
{
using (Graphics graphic = Graphics.FromImage(image))
{
graphic.DrawString("pangxiaoliang", enFont, new SolidBrush(Color.LightGray), 2, 2);
graphic.DrawString("pangxiaoliang", enFont, new SolidBrush(Color.Black), 0, 0);
}
Bitmap theBitmap = new Bitmap(image);
theBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
theBitmap.Dispose();
}
context.Response.ClearContent();
context.Response.ContentType = "image/jpg";
context.Response.BinaryWrite(ms.ToArray());
}
catch
{
Bitmap error = new Bitmap(context.Server.MapPath("Image/error.bmp"));
error.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
error.Dispose();
context.Response.ClearContent();
context.Response.ContentType = "image/jpg";
context.Response.BinaryWrite(ms.ToArray());
}
finally
{
ms.Close();
ms.Dispose();
context.Response.End();
}
}
public static void ReturnErrorImage(HttpContext context)
{
MemoryStream ms = new MemoryStream();
try
{
Bitmap error = new Bitmap(context.Server.MapPath("error.bmp"));
error.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
error.Dispose();
context.Response.ClearContent();
context.Response.ContentType = "image/jpg";
context.Response.BinaryWrite(ms.ToArray());
}
catch
{
}
finally
{
ms.Close();
ms.Dispose();
context.Response.End();
}
}
/// <summary>
/// 会产生graphics异常的PixelFormat
/// </summary>
private static PixelFormat[] indexedPixelFormats = { PixelFormat.Undefined, PixelFormat.DontCare,
PixelFormat.Format16bppArgb1555, PixelFormat.Format1bppIndexed, PixelFormat.Format4bppIndexed,
PixelFormat.Format8bppIndexed
};
/// <summary>
/// 判断图片的PixelFormat 是否在 引发异常的 PixelFormat 之中
/// </summary>
/// <param name="imgPixelFormat">原图片的PixelFormat</param>
/// <returns></returns>
private static bool IsPixelFormatIndexed(PixelFormat imgPixelFormat)
{
foreach (PixelFormat pf in indexedPixelFormats)
{
if (pf.Equals(imgPixelFormat)) return true;
}
return false;
}
}
}
防止盗链关键点在:
if (context.Request.Url.Authority == context.Request.UrlReferrer.Authority)
{
CommonDeal.DealImageRequest(context);
}
else
{
CommonDeal.ReturnErrorImage(context);
}
客户端请求gif图像路径“http://localhost:2868/Image/logo.gif”,则:
1)如果是本站内请求
context.Request.Url.Authority是请求的地址,即“http://localhost:2868”。
context.Request.UrlReferrer.Authority是引用地址(请求的站点),即“http://localhost:2868”。
所以此时返回客户端的是带有水印的正确图像。
2)如果是其他站盗链(“http://localhost:9999”)
context.Request.Url.Authority是请求的地址,即“http://localhost:2868”。
context.Request.UrlReferrer.Authority是引用地址(请求的站点),即“http://localhost:9999”。
所以此时返回客户端的是提示请勿盗链图像。