基于SpringBoot實(shí)現(xiàn)防盜鏈功能
一、防盜鏈概念
防盜鏈?zhǔn)且环N通過限制資源訪問來源的技術(shù),通常通過檢查 HTTP 請求頭中的 Referer 字段來實(shí)現(xiàn)。如果請求的來源不是允許的域名,則拒絕該請求。除此之外,還可以結(jié)合 Token 和時間戳進(jìn)一步提高安全性,確保鏈接只能在一定時間內(nèi)有效。
二、防盜鏈原理
- Referer 校驗(yàn):
- HTTP Referer 是瀏覽器在發(fā)送請求時附加的字段,用于標(biāo)明請求的來源頁面。
- 服務(wù)器可以通過檢查 Referer 是否屬于信任的域名,拒絕其他來源的訪問請求。
- Token 驗(yàn)證:
- 服務(wù)器為合法請求生成帶簽名的訪問鏈接(包含 Token),客戶端訪問時攜帶該 Token。
- 服務(wù)器通過驗(yàn)證 Token 是否正確來判斷請求合法性。
- 時間限制:
- 通過在請求中附帶時間戳參數(shù),限制鏈接的有效期。
- 服務(wù)器校驗(yàn)請求的時間戳與當(dāng)前時間的差值,超出范圍的請求將被拒絕。
通過以上三種機(jī)制,可以顯著提高資源防盜鏈的安全性。
三、項(xiàng)目結(jié)構(gòu)
以下是示例項(xiàng)目的目錄結(jié)構(gòu):
src
├── main
│ ├── java
│ │ └── com.demo
│ │ ├── DemoApplication.java
│ │ ├── filter
│ │ │ ├── StaticResourceFilter.java
│ │ │ ├── TokenValidator.java
│ │ │ └── TimeValidator.java
│ └── resources
│ └── static
│ └── images
└──711815.jpeg
四、核心代碼實(shí)現(xiàn)
1. 主應(yīng)用程序入口
package com.et;
import com.et.filter.StaticResourceFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public FilterRegistrationBean<StaticResourceFilter> staticResourceFilter() {
FilterRegistrationBean<StaticResourceFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new StaticResourceFilter());
registrationBean.addUrlPatterns("/images/*");
return registrationBean;
}
}
2. 靜態(tài)資源訪問過濾器
package com.et.filter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class StaticResourceFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// validate Referer
String referer = httpRequest.getHeader("Referer");
String allowedDomain = "http://localhost:8088";
if (referer == null || !referer.startsWith(allowedDomain)) {
httpResponse.getWriter().write("403 Forbidden: Hotlinking not allowed");
return;
}
// validate Token
if (!TokenValidator.validateToken(httpRequest, httpResponse)) {
return;
}
// validate Timestamp
if (!TimeValidator.validateTimestamp(httpRequest, httpResponse)) {
return;
}
chain.doFilter(request, response);
}
}
3. Token 驗(yàn)證工具
package com.et.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class TokenValidator {
public static boolean validateToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
String token = request.getParameter("token");
String validToken = "your-predefined-token"; //set your predefined token here
if (token == null || !token.equals(validToken)) {
response.getWriter().write("403 Forbidden: Invalid Token");
return false;
}
return true;
}
}
4. 時間限制驗(yàn)證工具
package com.et.filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Instant;
public class TimeValidator {
private static final long ALLOWED_TIME_DIFF = 300; // offset in seconds( 300 seconds)
public static boolean validateTimestamp(HttpServletRequest request, HttpServletResponse response) throws IOException {
String timestampStr = request.getParameter("timestamp");
if (timestampStr == null) {
response.getWriter().write("403 Forbidden: Missing Timestamp");
return false;
}
try {
long timestamp = Long.parseLong(timestampStr);
long currentTimestamp = Instant.now().getEpochSecond();
if (Math.abs(currentTimestamp - timestamp) > ALLOWED_TIME_DIFF) {
response.getWriter().write("403 Forbidden: Timestamp Expired");
return false;
}
} catch (NumberFormatException e) {
response.getWriter().write("403 Forbidden: Invalid Timestamp");
return false;
}
return true;
}
}
5. 靜態(tài)資源示例
將一個圖片文件711815.jpeg 放入 src/main/resources/static/images 文件夾中。
以上只是一些關(guān)鍵代碼。
五、測試方式
啟動 Spring Boot 項(xiàng)目。
測試訪問圖片資源:
curl -X GET "http://localhost:8088/static/example.jpg?token=your-predefined-token×tamp=$(date +%s)" -H "Referer: http://localhost:8088"
檢查以下情況:
- 如果 Referer 不正確,返回
403 Forbidden: Hotlinking not allowed。 - 如果 Token 無效,返回
403 Forbidden: Invalid Token。 - 如果時間戳超時,返回
403 Forbidden: Timestamp Expired。
- 如果 Referer 不正確,返回
通過本文,您可以了解如何通過 Referer 校驗(yàn)、Token 驗(yàn)證和時間限制實(shí)現(xiàn)資源防盜鏈保護(hù)。如果有其他問題或需求,歡迎進(jìn)一步探討!
到此這篇關(guān)于基于SpringBoot實(shí)現(xiàn)防盜鏈功能的文章就介紹到這了,更多相關(guān)SpringBoot防盜鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于String轉(zhuǎn)Json的幾種方式
這篇文章主要介紹了關(guān)于String轉(zhuǎn)Json的幾種方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
IDEA Maven Mybatis generator 自動生成代碼(實(shí)例講解)
下面小編就為大家分享一篇IDEA Maven Mybatis generator 自動生成代碼的實(shí)例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
Java基于正則實(shí)現(xiàn)的日期校驗(yàn)功能示例
這篇文章主要介紹了Java基于正則實(shí)現(xiàn)的日期校驗(yàn)功能,涉及java文件讀取、日期轉(zhuǎn)換及字符串正則匹配相關(guān)操作技巧,需要的朋友可以參考下2017-03-03
詳解SpringBoot和Mybatis配置多數(shù)據(jù)源
本篇文章主要介紹了詳解SpringBoot和Mybatis配置多數(shù)據(jù)源,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
解決rocketmq-client查詢手動發(fā)送消息異常問題
這篇文章主要介紹了解決rocketmq-client查詢手動發(fā)送消息異常問題,具有很好的參考價值,希望對大家大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA
這篇文章主要介紹了關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA的問題,文中提供了詳細(xì)的圖文講解,需要的朋友可以參考下,如果有錯誤的地方還請指正2023-03-03
Java導(dǎo)入新項(xiàng)目報錯java:JDK?isn‘t?specified?for?module解決辦法
這篇文章主要給大家介紹了關(guān)于Java導(dǎo)入新項(xiàng)目報錯java:JDK?isn‘t?specified?for?module的解決辦法,當(dāng)您在導(dǎo)入Java項(xiàng)目時遇到錯誤時,可以嘗試以下面的方法來處理,需要的朋友可以參考下2024-05-05
Java中使用Jedis操作Redis的實(shí)現(xiàn)代碼
本篇文章主要介紹了Java中使用Jedis操作Redis的實(shí)現(xiàn)代碼。詳細(xì)的介紹了Redis的安裝和在java中的操作,具有一定的參考價值,有興趣的可以了解一下2017-05-05

