使用場景:明明引用了一個正確的圖片地址,但顯示出來的卻是一個紅叉或寫有“此圖片僅限於***網站用戶交流溝通使用”之類的“假圖片”。用嗅探軟件找到了多媒體資源的真實地址用下載軟件仍然不能下載。下載一些資源時總是出錯,如果確認地址沒錯的話,大多數情況都是遇上防盜鏈系統了。常見的防盜鏈系統,一般使用在圖片、音視頻、軟件等相關的資源上。
實現原理:把當前請求的主機與服務器的主機進行比對,如果不一樣則就是惡意鏈接,反之則是正常鏈接。
不說了,直接上代碼:
- String address=request.getHeader("referer"); //獲取頁面的請求地址
- String pathAdd=""; //定義空字符串
- if(address!=null){ //判斷當前的頁面的請求地址為空時
- URL urlOne=new URL(address);//實例化URL方法
- pathAdd=urlOne.getHost(); //獲取請求頁面的服務器主機
- }
- String address1=request.getRequestURL().toString(); //獲取當前頁面的地址
- String pathAdd1="";
- if(address1!=null){
- URL urlTwo=new URL(address1);
- pathAdd1=urlTwo.getHost(); //獲取當前服務器的主機
- }
- if(!pathAdd.equals(pathAdd1)){ //判斷當前頁面的主機與服務器的主機是否相同
- }
使用Request對象設置頁面的防盜鏈
所謂的防盜鏈就是當你以一個非正常渠道去訪問某一個Web資源的時候,服務器會將你的請求忽略並且將你的當前請求變為按正常渠道訪問時的請求並返回到相應的頁面,用戶只有通過該頁面中的相關操作去訪問想要請求的最終資源。
例如,你有一個訪問某資源的網址,但是你事先不知道這個網址是有防盜鏈的,那么當你輸入該網址時你可能會發現,並沒有馬上跳轉到你想要的資源頁面而是一些無關的信息頁面,但是就是在這些信息頁面中你發現有一個超鏈接或是其他操作可以跳轉到你所訪問的最終資源頁面。
這就是防盜鏈技術了,好了來看一個具體應用:
- Request.java
- package net.csdn.request;import java.io.IOException;
- import java.io.PrintWriter;import java.util.Enumeration
- import javax.servlet.RequestDispatcher;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class Request extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {getDoorChain(request, response);}
- private void getDoorChain(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- String referer = request.getHeader("referer");
- if(referer==null || !referer.endsWith("http://localhost:8080/Request/index.jsp")){
- response.sendRedirect("http://localhost:8080/Request/index.jsp");
- return;
- }
- response.setCharacterEncoding("utf-8");
- response.setContentType("text/html;charset =utf-8");
- PrintWriter pw = response.getWriter();
- pw.write("喜劇片《東成西就》");
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
Request.java
package net.csdn.request;import java.io.IOException;
import java.io.PrintWriter;import java.util.Enumeration
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Request extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {getDoorChain(request, response);}
private void getDoorChain(HttpServletRequest request,
HttpServletResponse response) throws IOException {
String referer = request.getHeader("referer");
if(referer==null || !referer.endsWith("http://localhost:8080/Request/index.jsp")){
response.sendRedirect("http://localhost:8080/Request/index.jsp");
return;
}
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset =utf-8");
PrintWriter pw = response.getWriter();
pw.write("喜劇片《東成西就》");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- index.jsp
- <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"
- +request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css">
- -->
- </head>
- <body>
- 這里是防盜鏈技術的應用檢測! <br>
- <a href ="/Request/Request" >喜劇片 </a>
- </body>
- </html>
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"
+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
這里是防盜鏈技術的應用檢測! <br>
<a href ="/Request/Request" >喜劇片 </a>
</body>
</html>
效果如圖:

例如我最終想要通過http://lcoalhost:8080/Request/Request這個網址獲取到我想要的《東成西就》 的資源可是當我真正的輸入這個網址時,卻轉到了: http://localhost:8080/Request/index.jsp這個頁面
只有當你點擊“喜劇片”這個超鏈接時才會真正的得到你想要的資源頁面即:

好了趕快自己動手試一試吧!
今天我們來聊聊Java防盜鏈,多說無用,直接上應用案例。
這里所用的工具是報表軟件FineReport,搭配有決策系統(一個web前端展示系統,主要用於權限控制),可以采用java防盜鏈的方式來實現頁面權限。
瀏覽器中直接輸入報表URL的時候,它的頭文件是空的,因此,可以在訪問的時候做兩個判斷:頭文件是否為空以及以什么頁面進行跳轉,如果不符合跳到錯誤頁面即可。
什么是Referer?
這里的 Referer 指的是HTTP頭部的一個字段,也稱為HTTP來源地址(HTTP Referer),用來表示從哪兒鏈接到目前的網頁,采用的格式是URL。換句話說,借着 HTTP Referer 頭部網頁可以檢查訪客從哪里而來,這也常被用來對付偽造的跨網站請求。

什么是空Referer,什么時候會出現空Referer?
首先,我們對空Referer的定義為,Referer 頭部的內容為空,或者,一個HTTP請求中根本不包含Referer頭部。
那么什么時候HTTP請求會不包含Referer字段呢?根據Referer的定義,它的作用是指示一個請求是從哪里鏈接過來,那么當一個請求並不是由鏈接觸發產生的,那么自然也就不需要指定這個請求的鏈接來源。
比如,直接在瀏覽器的地址欄中輸入一個資源的URL地址,那么這種請求是不會包含Referer字段的,因為這是一個“憑空產生”的HTTP請求,並不是從一個地方鏈接過去的。

在防盜鏈設置中,允許空Referer和不允許空Referer有什么區別?
在防盜鏈中,如果允許包含空的Referer,那么通過瀏覽器地址欄直接訪問該資源URL是可以訪問到的;
但如果不允許包含空的Referer,那么通過瀏覽器直接訪問也是被禁止的。
操作步驟
1、添加class文件
編寫一個類文件,用來判斷頭文件是否為空,代碼如下:
package com.fr.test; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class Dodo implements Filter { public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String referer = req.getHeader("referer"); //下面的IP地址是正常頁面請求 if(null != referer && (referer.trim().startsWith("http://localhost:8033")||referer.trim().startsWith("http://www.finereporthelp.com/test/hello.html"))){ System.out.println("正常頁面請求"+referer); chain.doFilter(req, resp); //下面的就是出現不是正常頁面請求的時候跳轉 }else{ System.out.println("盜鏈"+referer); req.getRequestDispatcher("/LdapLogin.jsp").forward(req, resp); } } public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
將Dodo.java編譯成class文件,並放在%TOMCAT_HOME%\WebReport\WEB-INF\classes\com\fr\test目錄下。

2、修改web.xml文件
打開%TOMCAT_HOME%\webapps\WebReport\WEB-INF下的web.xml文件,配置一個過濾filter,在出現ReportServer的時候執行過濾,代碼如下:

<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>com.fr.test.Dodo</filter-class></filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/ReportServer</url-pattern> </filter-mapping>
兩步就可以搞定,如果屬於盜鏈,則跳轉至上述的LdapLogin錯誤頁面,這里沒有LdapLoign頁面,所以直接跳轉404。如果還想實現數據權限,則可以通過單點登錄或者session注入的方式。
效果測試
准備兩個html文件
假設hello.html是正確的網址
<html> <body> <p>測試</p> <a href="http://localhost:8033/WebReport/ReportServer?reportlet=demo%2Fnewchart%2Fothers%2FLogarithmic_axis.cpt&op=write">防盜鏈測試</a> </body> <html>
假設steal.html是盜鏈的網址
<html> <body> <p>測試,錯誤的鏈接地址</p> <a href="http://localhost:8033/WebReport/ReportServer?reportlet=demo%2Fnewchart%2Fothers%2FLogarithmic_axis.cpt&op=write">防盜鏈測試</a> </body> </html>
情況一
通過hello.html跳轉,跳轉鏈接正確,即referer不為空且正確


情況二


通過steal.html跳轉,跳轉鏈接錯誤,即referer不為空且錯誤
情況三

直接訪問URL地址,即referer為空

