一、摘要
对于你自己网站上的图片,你可能会希望它们只显示在自己网站的页面上,而当别人的网站引用它们时,不给予显示 ,或者显示一张自定义的警告图片 ,或者在图片上加上一个水印信息 ,告诉浏览者此图片是来自你的网站的。
使用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 <appsettings> 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信息写在图片上。
这里涉及到给图片添加水印的程序,由于之前介绍过给图片添加水印的类库,这里就直接引用了它来完成添加水印的过程。在图片上添加水印的原理请见:
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]