使用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>
这里我引用了百度,显示页面,这是因为百度有防盗链技术
但是当我引用一个没有防盗链技术的页面时
<iframe src="http://localhost:8080/web/" title="description"></iframe>
这里将引用换为我的tomcat服务器网页,显示成功!
3.如何防盗链
时间戳验证
时间戳防盗链主要是在url请求里,通过增加时间戳的信息来对url加上时间的因素,盗链者如果不及时更新url,那么就会无法访问。这个比较常见,但是如果盗链者定期的过来更新url,这种方法也会失效
IP黑白名单:
配置请求者的IP黑白名单,设置黑名单之后,除了黑名单的用户都能访问;反之设置了白名单,只有白名单的用户都可以访问。这个方法直接有效,但必须知道请求者的具体IP信息,所以适用的场景比较有限。
签名验证
给请求的内容加速一个加密的字符串,字符串内容不一致时,拒绝或替换请求内容
Referer验证
检查请求的来源网页是否是你允许的域名,如果不是,就拒绝或替换请求的内容。这种方法需要在服务器端配置相关的规则,如 Nginx 的 valid_referers 指令
4.reference实现简单的防盗链
实现原理:
在上图中用户一共发送两次请求,第一次访问正规服务器中的 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);
}
}
正常访问:,因为此时的请求地址
为什么可以访问呢,查看网络,可以发现正规渠道的referer是http://localhost:8080/web/download.jsp,我们代码中检查,服务端只有referer是这个referer时候,才会显示真实的页面
为什么呢?我们来看看referer的定义:
HTTP 协议的规定,referer 字段是用来表示请求的来源,也就是说,用户是从哪个网页点击了一个链接或者提交了一个表单,从而发出了这个请求。
也就是说我们的refer由我们的访问的页面决定,如果直接在浏览器中进入到一个页面,我们是没有referer的,从某个页面进去referer取决于那个页面,下图是我们假设我们在自己页面挂上防盗链后的结果,可以看到referer不对应,因此无法访问真正的页面