# 防盗链

## **防盗链的原理**

<mark style="color:blue;">**HTTP协议的请求头中存在一个Referer域，该域采用URL的格式表示访问当前网页或者文件的源地址。**</mark>

**通过Referer域的值**，我们可以检测到访问目标资源的源地址。这样，**如果我们检测到Referer头域中的值并不是自己站点内的URL，就采取阻止措施**，实现防盗链。

## valid\_referers指令

Nginx配置中有一个<mark style="color:blue;">**valid\_referers指令**</mark>，<mark style="color:blue;">**用来获取Referer头域中的值**</mark>，<mark style="color:blue;">**并且根据该值的情况给Nginx全局变量$invalid\_referer赋值**</mark>。

<mark style="color:orange;">**如果Referer头域中没有符合valid\_referers指令配置的值，$invalid\_referer变量将会被赋值为1。**</mark>

valid\_referers指令的语法结构为：

```nginx
valid_referers none | blocked | server_names | string ...;
```

* <mark style="color:blue;">**none**</mark>，检测**Referer头域不存在**的情况。
* <mark style="color:blue;">**blocked**</mark>，检测**Referer头域的值被防火墙或者代理服务器删除或伪装**的情况。这种情况下，该头域的值不以“http://”或者“https://”开头。
* <mark style="color:blue;">**server\_names**</mark>，设置**一个或多个URL，检测Referer头域的值是否是这些URL中的某个**。从Nginx 0.5.33以后**支持使用通配符“\*”**。

## 防盗链的实现

有了**valid\_referers指令**&#x548C;**$invalid\_referer变量**，就能**通过Rewrite功能来实现防盗链**。有两种实现方案：一种是**根据请求资源的资源类型**，一种是**根据请求目录**。

### **根据请求资源的资源类型**

```nginx
server
{
  …
  listen  80;
  server_name  www.myweb.name;
  location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$
  {
    …
    valid_referers  none  blocked  server_names  *.myweb.name;
    if ($invalid_referer)
    {
      rewrite  ^/  http://www.myweb.com/images/forbidden.png;
    }
  }
}
…
```

在上述配置中，当有网络连接对以gif、jpg、png为后缀的图片资源、以swf、flv为后缀的媒体资源、以rar、zip为后缀的压缩存档资源发起请求时，**如果检测到Referer头域中没有符合valid\_referers指令配置的值，就将客户端请求的URL重写为http://www.myweb.com/images/forbidden.png**，这防止了非法盗链行为。

当然**我们也可以不重写URL，直接返回HTTP错误状态，如403状态**。

### **根据请求目录**

```nginx
server
{
  …
  listen  80;
  server_name  www.myweb.name;
  location /file/
  {
    …
    root /server/file/;
    valid_referers  none  blocked  server_names  *.myweb.name;
    if ($invalid_referer)
    {
      rewrite  ^/  http://www.myweb.com/images/forbidden.png;
    }
  }
}
…
```

其原理和根据文件类型实现防盗链的原理是一样的，**只是在location块的uri变量上做了改变，对于请求服务器上\[root]/server/file/目录下的资源采取了防盗链措施**。
