防盗链原理与破防

防盗链测原理与破防
2021-04-24 13:53:00 0
本文 3078 个字,阅读需要大约 7 分钟
加载失败

文章目录 [回顶部]
[--评论--]

这是一个使用阿里云对象存储的文件,在当前网站内可以正常显示,右键复制图片地址,在当前浏览器打开,也可以正常下载。但是当复制这个图片地址,然后在新的浏览器打开,神奇的事情发生了。

![Screenshot from 2021-04-25 13-40-51](https://gallery-repository.oss-cn-hangzhou.aliyuncs.com/images/Screenshot from 2021-04-25 13-40-51.png)

为什么会发生这种事情呢?🐶

这就不得不提一下阿里云对象存储的防盗链原理了。

防盗链功能通过设置Referer白名单以及是否允许空Referer,限制仅白名单中的域名可以访问您Bucket内的资源。OSS支持基于HTTP和HTTPS header中表头字段Referer的方法设置防盗链。

是否进行防盗链验证的具体场景如下:

  • 仅当通过签名URL或者匿名访问Object时,进行防盗链验证。
  • 当请求的Header中包含Authorization字段,不进行防盗链验证。

防盗链通过请求Header中的Referer地址判断访问来源。当浏览器向Web服务器发送请求的时候,请求Header中将包含Referer,用于告知Web服务器该请求的页面链接来源。OSS根据浏览器附带的Referer与用户配置的Referer规则来判断允许或拒绝此请求,如果Referer一致,则OSS将允许该请求的访问;如果Referer不一致,则OSS将拒绝该请求的访问。例如,某个Bucket设置了Referer为https://10.10.10.10.com:

以上引用阿里云对象存储的防盗链说明,可以看出,阿里云对象存储的防盗链验证机制非常简单,

  • 就是在请求头中加入referer:{allow-string} 。关于当前网站静态资源结构说明,请看使用typora结合picgo和alioss编写markdown,发表blog ,alioss设置的权限是公共读,并开启oss验证,这样就需要在请求资源的时候,给响应加上referer。下面涉及nginx的部分配置,需要一定的nginx基础知识。

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
        add_header Referer https://www.xxxx.cn;
        expires 30d;
        access_log off;
      }
    

    nginx匹配静态资源,并将静态资源响应加上referer响应头。这样当浏览器再去请求这个资源的时候,就可以带着我们返回的响应头进行请求了。

  • 或者还有更加简单但是可能会出意外的方式:Authorization: xxxxxx。这个方式和上面是同样的原理,就是需要请求头中存在Authorization字段。但是请注意:这种验证方式,相当于让网站自己去做的验证,用户登录后,相当于对用户身份进行了验证,即避免了一大部分的盗链情况,如果非法用户伪造authorization字段,虽然无法正常登录,但是可以轻松盗图,仔细一想,非法用户也不用登录啊,只是偷一个图片而已。正常登录的用户,访问图片不算盗图,非法用户轻松盗图而不必真正登录.....哎,这个设计是如此的愚蠢 😂 .(@阿里工程师)。

有了破防原理,下面讲讲各种爬虫应该如何破防盗链。

  • python

    
    import requests
     
    url1='https://baijiahao.baidu.com/s?id=1697976987508204190&wfr=spider&for=pc'
    #添加请求头
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE',
        'Referer': 'allow-string'
    }
    response_1=requests.get(url1, headers=headers)
    
  • php

    function http_post($sUrl, $aHeader, $aData){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $sUrl);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($aData));
        $sResult = curl_exec($ch);
        if($sError=curl_error($ch)){
            die($sError);
        }
        curl_close($ch);
        return $sResult;
    }
     
    $url = 'https://www.example.com;
    $header = array('User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36','Referer:allow-string');
    $data = array();
    $data = http_post($url,$header,$data);
    
  • go

    package main
    import (
      "fmt"
      "io/ioutil"
      "net/http"         
      "os"
      "encoding/json"
    )
    
    func main() { //生成client 参数为默认
      client := &http.Client{}
      //生成要访问的url
      url := "http://somesite/somepath/"
      //提交请求
      reqest, err := http.NewRequest("GET", url, nil)
    
      //增加header选项
      reqest.Header.Add("Cookie", "xxxxxx")
      reqest.Header.Add("User-Agent", "xxx")
      reqest.Header.Add("X-Requested-With", "xxxx")
      reqest.Header.Add("Referer", "allow-string")
    
      if err != nil {
        panic(err)
      }  
      //处理返回结果
      response, _ := client.Do(reqest)
      defer response.Body.Close()
    
  • java

    HttpResponse response = null;  
        HttpGet get = new HttpGet(url);  
        get.addHeader("Accept", "text/html");  
        get.addHeader("Accept-Charset", "utf-8");  
        get.addHeader("Accept-Encoding", "gzip");  
        get.addHeader("Accept-Language", "en-US,en");  
        get.addHeader("Referer", "allow-string");  
        get.addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22");  
        response = client.execute(get);  
        HttpEntity entity = response.getEntity();  
        Header header = entity.getContentEncoding();  
        if (header != null)  
        {  
            HeaderElement[] codecs = header.getElements();  
            for (int i = 0; i < codecs.length; i++)  
            {  
                if (codecs[i].getName().equalsIgnoreCase("gzip"))  
                {  
                    response.setEntity(new GzipDecompressingEntity(entity));  
                }  
            }  
        }  
        return response;
    
以上就是本文的全部内容啦,有什么疑问欢迎在下方评论区留言嗷,收到通知会及时回复~
文章浏览总量:968 (非即时 )
Comments
Nothing...
||||
# markdown..
 
100:0
推荐文章 使用余弦向量算法进行推荐(分数)
跳转到顶部