一、摘要
对于你自己网站上的图片,你可能会希望它们只显示在自己网站的页面上,而当别人的网站引用它们时,不给予显示,或者显示一张自定义的警告图片,或者在图片上加上一个水印信息,告诉浏览者此图片是来自你的网站的。
使用ASP.NET的HttpHandler可以很方便地达到这样的效果。
二、实现步骤
1. 在网站项目中添加一个类文件,实现IHttpHandler接口
2. 配置Web.Config,将图片文件的请求映射到第1步中的类处理程序
下面先讲第1步配置Web.Config,再讲第1步。因为配置非常简单,而类文件则需要一些代码,将会分三种情况给出这个类文件的三个版本。
三、配置Web.Config详解
假设第1步的类文件命名为ImageGuardHandler.cs,该文件定义了一个位于命名空间 zizhujy.HttpHandlers 下的类 ImageGuardHandler。现在配置Web.Config,使得图片文件请求被转交到ImageGuardHandler来处理。
如果网站服务器是使用的IIS 7.5或以上,则只需按如下格式配置:
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
...
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<add name="ImageGuardHandlerPng" path="*.png" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/>
<add name="ImageGuardHandlerGif" path="*.gif" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/>
<add name="ImageGuardHandlerJpg" path="*.jpg" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/>
</handlers>
</system.webServer>
...
</configuration>
如上,配置了对于三种图片文件(.png, .gif, .jpg)的请求,将会被ImageGuardHandler处理。
如果使用的是 IIS 5.1,则需要按如下格式配置:
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
...
<system.web>
<httpHandlers>
<add path="*.gif" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
<add path="*.png" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
<add path="*.jpg" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
</httpHandlers>
</system.web>
...
</configuration>
四、处理程序ImageGuardHandler详解
1. 对于来自非本网站的图片请求给予拒绝服务的响应:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;
namespace zizhujy.HttpHandlers
{
public class ImageGuardHandler : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse response = context.Response;
HttpRequest request = context.Request;
string imagePath = null;
// Check whether the page requesting the image is from your site.
if (request.UrlReferrer != null)
{
// Perform a case-insensitive comparison of the referer.
if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
{
// The requesting host is correct.
// Allow the image to be served(if it exists).
imagePath = request.PhysicalPath;
if (!File.Exists(imagePath))
{
response.Status = "Image not found";
response.StatusCode = 404;
return;
}
}
}
if (imagePath == null)
{
response.Status = "Not allowed";
response.StatusCode = 500;
return;
}
// Set the content type to the appropriate image type.
response.ContentType = "image/" + Path.GetExtension(imagePath).ToLower();
// Serve the image.
response.WriteFile(imagePath);
//Image image = Image.FromFile(imagePath);
//image = ImageHandler.WatermarkHandler.AddCopyrightText(image, "www.zizhujy.com", ImageHandler.CopyrightPosition.BottomRight);
//image.Save(response.OutputStream, GetImageFormatByExtension(Path.GetExtension(imagePath)));
//image.Dispose();
}
public bool IsReusable
{
get { return true; }
}
}
}
2. 对于来自非本网站的图片请求,显示一张自定义的警告图片,这个警告图片的路径可以配置在Web.Config中的 节中,如:
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
...
<appSettings>
<httpHandlers>
<add key="NotAllowedImage" value="~/Content/Images/NotAllowed.gif"/>
</httpHandlers>
</appSettings>
...
</configuration>
ImageGuardHandler.cs代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;
namespace zizhujy.HttpHandlers
{
public class ImageGuardHandler : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse response = context.Response;
HttpRequest request = context.Request;
string imagePath = null;
// Check whether the page requesting the image is from your site.
if (request.UrlReferrer != null)
{
// Perform a case-insensitive comparison of the referer.
if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
{
// The requesting host is correct.
// Allow the image to be served(if it exists).
imagePath = request.PhysicalPath;
if (!File.Exists(imagePath))
{
response.Status = "Image not found";
response.StatusCode = 404;
return;
}
}
}
if (imagePath == null)
{
// No valid image was allowed.
// Return the warning image instead of the requested image.
// Rather than hard-code this image, you could retrieve it from the web.config file (using the section or a custom section).
//imagePath = context.Server.MapPath("~/Images/notAllowed.gif");
imagePath = context.Server.MapPath(System.Configuration.ConfigurationManager.AppSettings.Get("NotAllowedImage").ToString());
}
// Set the content type to the appropriate image type.
response.ContentType = "image/" + Path.GetExtension(imagePath).ToLower();
// Serve the image.
response.WriteFile(imagePath);
//Image image = Image.FromFile(imagePath);
//image = ImageHandler.WatermarkHandler.AddCopyrightText(image, "www.zizhujy.com", ImageHandler.CopyrightPosition.BottomRight);
//image.Save(response.OutputStream, GetImageFormatByExtension(Path.GetExtension(imagePath)));
//image.Dispose();
}
public bool IsReusable
{
get { return true; }
}
}
}
3. 对于来自非本网站的图片请求,在图片上加上一行水印文本,将自己网站的Url信息写在图片上。
这里涉及到给图片添加水印的程序,由于之前介绍过给图片添加水印的类库,这里就直接引用了它来完成添加水印的过程。在图片上添加水印的原理请见:
使用.NET的GDI+技术给图片加水印
ImageGuardHandler.cs文件源码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;
namespace zizhujy.HttpHandlers
{
public class ImageGuardHandler : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse response = context.Response;
HttpRequest request = context.Request;
string imagePath = null;
// Check whether the page requesting the image is from your site.
if (request.UrlReferrer != null)
{
// Perform a case-insensitive comparison of the referer.
if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
{
// The requesting host is correct.
// Allow the image to be served(if it exists).
imagePath = request.PhysicalPath;
if (!File.Exists(imagePath))
{
response.Status = "Image not found";
response.StatusCode = 404;
return;
}
else
{
// Serve the image normally
response.WriteFile(imagePath);
return;
}
}
else
{
// Add watermark to the image
imagePath = request.PhysicalPath;
// Set the content type to the appropriate image type.
response.ContentType = "image/" + Path.GetExtension(imagePath).Replace(".", "").ToLower();
// Serve the image.
Image image = Image.FromFile(imagePath);
ImageHandler.TextWatermarker txtWatermarker = new ImageHandler.TextWatermarker(image, "www.zizhujy.com");
txtWatermarker.AddWatermark();
image = txtWatermarker.WatermarkedImage;
//image.Save(response.OutputStream, ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath)));
MemoryStream mem = new MemoryStream();
image.Save(mem, ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath)));
// Write the MemoryStream data to the OutputStream
mem.WriteTo(response.OutputStream);
mem.Dispose();
image.Dispose();
txtWatermarker.Dispose();
return;
}
}
else
{
// Add watermark to the image
imagePath = request.PhysicalPath;
// Set the content type to the appropriate image type.
response.ContentType = "image/" + Path.GetExtension(imagePath).Replace(".","").ToLower();
// Serve the image.
Image image = Image.FromFile(imagePath);
ImageHandler.TextWatermarker txtWatermarker = new ImageHandler.TextWatermarker(image, "www.zizhujy.com");
txtWatermarker.AddWatermark();
image = txtWatermarker.WatermarkedImage;
// If the image is in PNG format, then it can be saved into response.OutputStream directly
ImageFormat format = ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath));
//if (format.Equals(ImageFormat.Png))
if (true)
{
// Create the PNG in memory
MemoryStream mem = new MemoryStream();
image.Save(mem, ImageFormat.Png);
// Write the MemoryStream data to the output stream.
mem.WriteTo(response.OutputStream);
mem.Dispose();
}
else
{
image.Save(response.OutputStream, format);
}
image.Dispose();
txtWatermarker.Dispose();
return;
}
}
public bool IsReusable
{
get { return true; }
}
}
}
五、结语
以上三种版本的HttpHandler处理程序类,只需要任选其一即可。甚至可以整合成一个类,然后在Web.Config中作相关的配置,以控制其是直接拒绝服务,还是显示警告图片,或者是添加水印信息。
[donate: www.zizhujy.com]