使用ServletHttp实现一个防盗链

1.什么是盗链

定义:利用技术手段,在不经过原始内容提供者的同意或授权的情况下,将其网站上的内容直接显示在自己的网站上,或者通过链接的方式,让用户可以直接访问到原始内容提供者的网站上的内容。

简单说就是:

如果一个我的网站没有经过百度的同意或授权,就在我的网站上显示或链接网站B的图片、视频、文章等内容,那么我的这个网站就是在进行盗链。

举个例子:现在别人在我的网站访问一个页面,这个页面却不是我的,我将百度链接展示给他,那么我这就叫盗链,而高明的盗链甚至会包装成你发觉不了的页面,让你没办法发现是百度

2.怎么实现盗链?

实现的方法有很多,比如

客户端技术:

利用 JavaScript 或 jQuery 等脚本语言,在浏览器端动态地从目标网页获取内容,并插入到自己的网页中,但是这种方法需要考虑跨域的问题

服务端技术

从目标网页获取内容,然后过滤、解析、修改后,再输出到自己的网页中。这种方法需要使用一些编程语言,如 PHP、Python、Java 等,以及一些网络库或框架,如 cURL、Requests、BeautifulSoup、Jsoup 等

前端技术

其中之一:

使用 iframe 标签,可以在自己的网页中嵌入其他网页的整个内容,只需要指定 src 属性为目标网页的 URL 即可。

这简单举例一下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<iframe src="https://www.baidu.com/" title="description"></iframe>
	</body>
</html>

这里我引用了百度,显示页面,这是因为百度有防盗链技术

image-20231015105511017

但是当我引用一个没有防盗链技术的页面时

		<iframe src="http://localhost:8080/web/" title="description"></iframe>

这里将引用换为我的tomcat服务器网页,显示成功!

image-20231015105737133

3.如何防盗链

时间戳验证

时间戳防盗链主要是在url请求里,通过增加时间戳的信息来对url加上时间的因素,盗链者如果不及时更新url,那么就会无法访问。这个比较常见,但是如果盗链者定期的过来更新url,这种方法也会失效

IP黑白名单:

配置请求者的IP黑白名单,设置黑名单之后,除了黑名单的用户都能访问;反之设置了白名单,只有白名单的用户都可以访问。这个方法直接有效,但必须知道请求者的具体IP信息,所以适用的场景比较有限。

签名验证

给请求的内容加速一个加密的字符串,字符串内容不一致时,拒绝或替换请求内容

Referer验证

检查请求的来源网页是否是你允许的域名,如果不是,就拒绝或替换请求的内容。这种方法需要在服务器端配置相关的规则,如 Nginx 的 valid_referers 指令

4.reference实现简单的防盗链

实现原理:

image-20231015110825200

在上图中用户一共发送两次请求,第一次访问正规服务器中的 download.jsp 页面,第二次访问盗链者服务器中的 download.jsp 页面,二个 download.jsp 页面虽然内容相同,但来源不相同。

  • 如果 download.jsp 中的请求,来源于盗链者服务器,我们就显示不可以下载;
  • 如果 download.jsp 中的请求,来源于正规服务器,我们就显示可以下载;

预期结果

  • 两次请求同一个域名,显示可以下载
  • 两次请求不同域名,显示无法下载

实现

@WebServlet(name = "DownloadServlet", urlPatterns = "/downloadServlet")
public class referer extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //设置响应内容和编码
        resp.setContentType("text/html;charset=utf-8");
        //获取响应对象的字符输出流
        PrintWriter writer = resp.getWriter();
        String referer = req.getHeader("referer");
        //请求头的referer存在并且来自正规服务器
        if(referer!=null&&referer.equals("http://localhost:8080/web/download.jsp")){
            writer.write("可以下载");
        }else{
            writer.write("拒绝盗链");
        }
        writer.flush();
        writer.close();
    }



    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

正常访问:,因为此时的请求地址

image-20231015125647835

image-20231015125707949

为什么可以访问呢,查看网络,可以发现正规渠道的referer是http://localhost:8080/web/download.jsp,我们代码中检查,服务端只有referer是这个referer时候,才会显示真实的页面

image-20231015130024515

为什么呢?我们来看看referer的定义:

HTTP 协议的规定,referer 字段是用来表示请求的来源,也就是说,用户是从哪个网页点击了一个链接或者提交了一个表单,从而发出了这个请求。

也就是说我们的refer由我们的访问的页面决定,如果直接在浏览器中进入到一个页面,我们是没有referer的,从某个页面进去referer取决于那个页面,下图是我们假设我们在自己页面挂上防盗链后的结果,可以看到referer不对应,因此无法访问真正的页面

image-20231015130753227