基于SpringBoot實現(xiàn)防盜鏈功能
一、防盜鏈概念
防盜鏈是一種通過限制資源訪問來源的技術,通常通過檢查 HTTP 請求頭中的 Referer
字段來實現(xiàn)。如果請求的來源不是允許的域名,則拒絕該請求。除此之外,還可以結合 Token
和時間戳進一步提高安全性,確保鏈接只能在一定時間內有效。
二、防盜鏈原理
- Referer 校驗:
- HTTP Referer 是瀏覽器在發(fā)送請求時附加的字段,用于標明請求的來源頁面。
- 服務器可以通過檢查 Referer 是否屬于信任的域名,拒絕其他來源的訪問請求。
- Token 驗證:
- 服務器為合法請求生成帶簽名的訪問鏈接(包含 Token),客戶端訪問時攜帶該 Token。
- 服務器通過驗證 Token 是否正確來判斷請求合法性。
- 時間限制:
- 通過在請求中附帶時間戳參數(shù),限制鏈接的有效期。
- 服務器校驗請求的時間戳與當前時間的差值,超出范圍的請求將被拒絕。
通過以上三種機制,可以顯著提高資源防盜鏈的安全性。
三、項目結構
以下是示例項目的目錄結構:
src ├── main │ ├── java │ │ └── com.demo │ │ ├── DemoApplication.java │ │ ├── filter │ │ │ ├── StaticResourceFilter.java │ │ │ ├── TokenValidator.java │ │ │ └── TimeValidator.java │ └── resources │ └── static │ └── images └──711815.jpeg
四、核心代碼實現(xiàn)
1. 主應用程序入口
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 驗證工具
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. 時間限制驗證工具
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
文件夾中。
以上只是一些關鍵代碼。
五、測試方式
啟動 Spring Boot 項目。
測試訪問圖片資源:
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 校驗、Token 驗證和時間限制實現(xiàn)資源防盜鏈保護。如果有其他問題或需求,歡迎進一步探討!
到此這篇關于基于SpringBoot實現(xiàn)防盜鏈功能的文章就介紹到這了,更多相關SpringBoot防盜鏈內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot如何讀取xml配置bean(@ImportResource)
這篇文章主要介紹了SpringBoot如何讀取xml配置bean(@ImportResource),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Kafka是什么及如何使用SpringBoot對接Kafka(最新推薦)
這篇文章主要介紹了Kafka是什么,以及如何使用SpringBoot對接Kafka,今天我們通過一個Demo講解了在SpringBoot中如何對接Kafka,也介紹了下關鍵類?KafkaTemplate,需要的朋友可以參考下2023-11-11