asp.net MVC 网站图片防盗链的几种方法

                                目录css

1. 经过 URL Rewrite Module 组件html

2. 经过 nginx 图片防盗链nginx

3.自定义 HttpHandler 处理web

4. 经过 MVC 自定义路由规则防盗链面试

5. 经过 MVC 自定义 RouteHandler 防盗链正则表达式

6. 经过 HttpModModule 防盗链json

7. 涉及知识点,相关资源windows

 

      

本身网站上的图片被别的网站盗用是一件很使人厌恶的事情,下面是处理图片盗链的几种方法。服务器

在这里先交代一下环境,我用的是 MVC4 ,IIS7 应用程序池为集成模式,如下配置都是基于此环境进行。负载均衡

1. 经过 URL Rewrite Module 组件

这是一个比较简单,方便的方法。首先要去 Url Rewite 官网 下载 URL Rewrite Module 2.0 并安装。安装完成后能够看到 IIS设置里多了  URL重写 的模块以下图:

在这里,能够对URL访问规则进行设置, 双击 URL 重写,添加入站规则

     

   

 

 在条件(c)  里面添加  {HTTP_REFERER}    模式为: ^http://localhost/.*$, 意思是 请求  HTTP_REFERER 必须包含 http://localhost/ 字符,规则固然是根据本身的状况写。

添加保存后,站点的 web.config 文件的 system.webServer 节点下就多了 rewrite 节点,配置以下。

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />    
    <handlers>
      <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" />
    </handlers>
        <rewrite>
            <rules>
                <rule name="防盗链" stopProcessing="true">
                    <match url=".*\.(gif|jpg|png)" />
                    <conditions> 
                        <add input="{HTTP_REFERER}" pattern="^http://localhost/.*$" negate="true" />
                    </conditions>
                    
                    <action type="Redirect" url="http://www.baidu.com" />
                </rule>
            </rules>
        </rewrite>
  </system.webServer>

配置好了,有没有效果呢,咱们作一个测试页面试试

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <img src="Content/webpage/img/111.jpg" />
    <img src="111.jpg"/>
</body>
</html>

      里面有2张图片,因为在IIS “入站规则条件” 里面配置的  HTTP_REFERER  正则表达式为 ^http://localhost/.*$  若是规则有效,咱们访问 http://localhost/HtmlPage1.html  图片应正常显示,而若是经过  http://127.0.0.1/HtmlPage1.html  访问是不该该显示图片的,下面是我经过这两个地址访问效果。

   

说明配置是成功的。固然了,URL Rewrite Module 并不是仅仅作图片防盗链哟!

 

2. 经过 nginx 图片防盗链

 

防盗链的原理都是同样的,主要是经过 referer 判断来源站点,若是来源站点不在 “白名单” 里,则拒绝或返回一张默认图片

 

location ~.*\.(jpg|gif|png)$ {
     valid_referers none blocked *.abc.com abc.com;
     if ($invalid_referer) {
     #rewrite ^/ http://abc.com/error.html;
     return 403;
      }
}
location ~.*\.(jpg|gif|png)$  表示全部 以 jpg|gif|png 为后缀名的文件都进行防盗链处理
valid_referers none blocked *.abc.com abc.com;   验证 referer  其中 none 表示直接访问的,不存在referer   blocked为根据防火墙假装的 referer 
#rewrite ^/ http://abc.com/error.html;  若是图片是放盗链,重定向到 地址 http://abc.com/error.html,通常是图片地址,可是要注意,这个图片地址不仅能在此防盗链规则里,不然也访问不到。

对 nginx 配置不熟悉的同窗请参考 windows 下配置 Nginx 常见问题

3.自定义 HttpHandler
处理

方法步骤: 1 建立自定义 handlers 代码以下,根据 Referre 判断请求来源,若是符合标准,输出文件流,不然中止响应。也能够输出一个特定的图片。
namespace WeiXinDemo.Globals
{
    /// <summary>
    /// 测试 Handler 实现图片防盗链
    /// </summary>
    public class MyImgHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }
         
        public void ProcessRequest(HttpContext context)
        {
            var response = context.Response;
            var request = context.Request; if (request.UrlReferrer == null || !WebApplication.ImgHost.Equals(request.UrlReferrer.Host))
            {
                response.End();
                return;
            }

            var fileName = context.Server.MapPath(request.FilePath);
            response.WriteFile(fileName);

            if (request.UrlReferrer == null || WebApplication.ImgHost.Equals(request.UrlReferrer.Host))
            {
                response.WriteFile(fileName);
            }
            else
            {
                response.End();
            }
        } 
    }
}


2 在web.config 文件 handlers 节点下添加自定义 Handler,知足要求的请求进入 WeiXinDemo.Globals.MyImgHandler 进行处理
<system.webServer> 
    <handlers>
      <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" />
    <!-- 这是添加的自定义Handler -->
<add name="jpgHandler" path="*.jpg" verb="*" type="WeiXinDemo.Globals.MyImgHandler,WeixinDemo" />
    <add name="pngHandler" path="*.png" verb="*" type="WeiXinDemo.Globals.MyImgHandler,WeixinDemo" />
<add name="bmpHandler" path="**.bmp" verb="*" type="WeiXinDemo.Globals.MyImgHandler,WeixinDemo" />
<add name="gifHandler" path="*.gif" verb="*" type="WeiXinDemo.Globals.MyImgHandler,WeixinDemo" />
</handlers> </system.webServer>

4. 经过 MVC 自定义路由规则防盗链

首先咱们要在 web.config 文件里 system.webServer 节点下 设置<modules runAllManagedModulesForAllRequests="true" /> 同时还要在 RouteConfig.cs 文件里添加 routes.RouteExistingFiles = true;确保全部路由都经过 RouteCollection 匹配 。
在这里咱们须要了解 UrlRoutingModule,它是System.Web.Routing的一部分。UrlRoutingModule用于检验请求的url和本地硬盘 中的文件能不能相匹配。若是匹配,则交给IIS处理。若是不匹配它会检验 RouteCollection 来决定能不能继续传递请求。而设置了 runAllManagedModulesForAllRequests="true" 后,会改变默认行为,全部请求都需要 运用 Routing来处理。
<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true" />    
    <handlers>
      <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" />
    </handlers> 
  </system.webServer>

     配置文件设置好之后添加自定义路由规则,下面是自定义路由规则的实现代码,其实里面就作了一件事,使用正则表达式判断当前请求是否符合规则,若是符合规则,则进入指定的处理页面,不然去匹配其余的路由规则。

 
namespace WeiXinDemo.Globals
{
    /// <summary>
    /// 图片路由规则(自定义)
    /// </summary>
    public class ImgRouteRule : IRouteConstraint
    {  
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            var regex = new Regex(@"/[^/]+(.jpg|.bmp|.gif|.png)");
            var result = regex.IsMatch(httpContext.Request.RawUrl); 
            return result;
        }
    }
}
 

    这样就形成了一个问题,全部的请求(好比 .css  .js  .htm 等等)都去路由规则里面去匹配,若是在路由规则里面匹配不到那么就会返回 404,如何避免呢?经过 RouteConfig.cs 文件配置忽略。

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            //确保全部路由都经过 RouteCollection 匹配(图片防盗链)
            routes.RouteExistingFiles = true;

            //忽略 json,html,js,css文件
            routes.IgnoreRoute("{*pathInfo}", new { pathInfo = @".+(.json|.html|.js|.css)" });
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 //符合路由规则的转到控制器 ImgRule/Index 处理 (自定义路由规则实现 图片防盗链)
            routes.MapRoute(
                name: "ImagesRoute",
                url: "{*catchall}",
                defaults: new { controller = "ImgRule", action = "Index" },
                // ImgRouteRule 为自定义路由规则,符合此规则,进入路由 访问 ImgRule/Index 
                constraints: new { customConstraint = new ImgRouteRule() },
                //控制器类命名空间
                namespaces: new[] { "WeiXinDemo.Controllers" });

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );            
        }
    }

    在上面的代码里配置了 "ImagesRoute"   的路由,使用的自定义路由规则,当知足规则时,跳转到 ImgRule/Index 去处理,处理代码跟使用 HttpHandler 相似

 public class ImgRuleController : Controller
    {
        // GET: ImgRule
        public FileStreamResult Index()
        {
            var fPath = Server.MapPath("~" + Request.FilePath);
            if (Request.UrlReferrer == null)   return null;            

            if (!System.IO.File.Exists(fPath) || !WebApplication.ImgHost.Equals(Request.UrlReferrer.Host) || !WebApplication.ImgHost.Equals(Request.UrlReferrer.Host))            
                return null; 
            return GetFile(fPath);
        }

        private FileStreamResult GetFile(string fPath)
        { 
            return File(new FileStream(fPath, FileMode.Open, FileAccess.Read), GetContentType(Request.FilePath));
        }

        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;
        }
    }

5. 经过
MVC 自定义 RouteHandler 防盗链
注意这里是自定义路由,别跟第4种方法混淆了,这里是指定自定义路由处理图片。
1 web.config 文件配置同第4种方法,也要开启 runAllManagedModulesForAllRequests="true"
2 建立自定义路由,自定义路实现代码以下 ImageRouteHandler ,同时还有自定义路由调用的 HttpHandlerImageHandler
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Routing;

namespace WeiXinDemo.Globals
{
    /// <summary>
    /// 测试自定义 RouteHandler 图片防盗链
    /// </summary>
    public class ImageRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        { 
            return new ImageHandler();
        }
    }
     
    /// <summary>
    /// 自定义路由调用的 HttpHandler
    /// </summary>
    public class ImageHandler : IHttpHandler
    {
        public ImageHandler()
        {
            
        }
         
        public bool IsReusable
        {
            get
            {
                return true;
            }
        } 

        public void ProcessRequest(HttpContext context)
        {
            var response = context.Response;
            var request = context.Request; if (request.UrlReferrer == null || !WebApplication.ImgHost.Equals(request.UrlReferrer.Host))
            {
                response.End();
                return;
            }

            var fileName = context.Server.MapPath(request.FilePath);
            response.WriteFile(fileName);  
        }
    }
}

     RouteConfig.cs 文件配置 以下,这里指定了 对根目录下的 jpg 文件的访问进入指定路由处理程序 ImageRouteHandler。    其实这里能够把图片都放在某一个特定文件夹下,而后对这个文件夹下文件的访问作放盗链。

namespace WeiXinDemo
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            //确保全部路由都经过 RouteCollection 匹配(图片防盗链)
            routes.RouteExistingFiles = true;

            //忽略 json,html,js,css文件
            routes.IgnoreRoute("{*pathInfo}", new { pathInfo = @".+(.json|.html|.js|.css)" });
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            //图片防盗链
            routes.Add("ImagesRoute",
                new Route("{name}.jpg", new ImageRouteHandler()));
 
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
            
        }
    }
}

6. 经过
HttpModule 防盗链
1. 修改 web.config 配置文件  
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" >
      <add   name="ImgModule" type="WeiXinDemo.Globals.ImageModel,WeiXinDemo"/>
    </modules> 
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" /> 
    </handlers>       
  </system.webServer>

2. 建立实现 IHttpModule 接口的 ImageModel

using System;
using System.Text.RegularExpressions;
using System.Web;

namespace WeiXinDemo.Globals
{
    /// <summary>
    /// 测试 HttpModel 图片防盗链
    /// </summary>
    public class ImageModel : IHttpModule
    {
        public void Dispose()
        {
        }
public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(BeginRequest); } void BeginRequest(object sender, EventArgs e) { HttpApplication context = (HttpApplication)sender; var regex = new Regex(@"/[^/]+(.jpg|.bmp|.gif|.png)"); var request = context.Context.Request; if (!regex.IsMatch(request.RawUrl)) return; if (request.UrlReferrer == null || !WebApplication.ImgHost.Equals(request.UrlReferrer.Host)) { context.Context.Response.End(); return; } var fileName = context.Context.Server.MapPath(request.FilePath); context.Context.Response.WriteFile(fileName); } } }

3.  RouteConfig.cs 文件忽略不须要防盗链的静态资源

using System.Web.Mvc;
using System.Web.Routing;

namespace WeiXinDemo
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            //确保全部路由都经过 RouteCollection 匹配(图片防盗链)
            routes.RouteExistingFiles = true;

            //忽略 json,html,js,css文件
            routes.IgnoreRoute("{*pathInfo}", new { pathInfo = @".+(.json|.html|.js|.css)" });
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );            
        }
    }
}

 

7. 涉及知识

本文只作了一件事情,图片防盗链,其实从不一样的实现方式来看它涉及到不一样的知识。

1. URL Rewrite Module  组件的使用

 如何使用mod_rewrite模块完成URL重写

 Creating Rewrite Rules for the URL Rewrite Module

2.  Nginx

借助Nginx搭建反向代理服务器

使用nginx实施负载均衡

3. IIS 工做原理,asp.net 管线

 IIS是如何处理ASP.NET请求的

ASP.NET那点鲜为人知的事

IIS 内部运行机制

ASP.NET MVC5请求管道和生命周期

ASP.NET MVC请求处理管道生命周期的19个关键环节(1-6)

4. Mvc UrlRouting 处理机制

MVC以前的那点事儿系列(8):UrlRouting的理解

 

    本文只是在这里探讨了一下实现防盗链的方法,没有考虑性能的问题,若是考虑性能跟简便性,我我的喜欢用 第 1 和第 2种实现方式,第 3种 次之。 条条大路通罗马,就看那种方法最适合。

相关文章
相关标签/搜索