基于SpringBoot實(shí)現(xiàn)圖片防盜鏈的兩種方式
1. 實(shí)現(xiàn)目的
出于安全和性能的考慮,我們希望服務(wù)器返回的圖片資源僅在指定網(wǎng)站內(nèi)展示,防止爬蟲(chóng)或其它站點(diǎn)直接引用圖片地址進(jìn)行下載或展示,進(jìn)而消耗服務(wù)器資源。簡(jiǎn)單來(lái)說(shuō),即在請(qǐng)求圖片時(shí)通過(guò)檢查 HTTP 請(qǐng)求頭中的 Referer 來(lái)判斷請(qǐng)求來(lái)源是否合法。
2. 簡(jiǎn)易實(shí)現(xiàn)方案
2.1 攔截器基本實(shí)現(xiàn)
在第一種方案中,代碼寫(xiě)死了允許訪問(wèn)的域名(例如 “baidudu.com”),主要步驟如下:
判斷 URL 后綴
當(dāng)請(qǐng)求 URL 以 “.jpg”、“.png”、“.jpeg” 等圖片格式結(jié)尾時(shí),再進(jìn)行后續(xù)判斷。檢查 Referer
從請(qǐng)求頭中取出 Referer,若不為空且包含預(yù)設(shè)允許的域名,則放行;否則返回 403 錯(cuò)誤碼,從而拒絕訪問(wèn)。
例如:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestUrl = request.getRequestURL().toString(); if (requestUrl.endsWith(".jpg") || requestUrl.endsWith(".png") || requestUrl.endsWith(".jpeg")) { String referer = request.getHeader("Referer"); if (referer != null && referer.contains("baidudu.com")) { return true; } else { response.sendError(HttpServletResponse.SC_FORBIDDEN); return false; } } return true; }
注冊(cè)攔截器時(shí),采用 Spring Boot 的 WebMvcConfigurer
接口將該攔截器應(yīng)用于所有請(qǐng)求路徑。
3. 靈活配置實(shí)現(xiàn)方案
為了使防盜鏈的配置更加靈活,可以將配置項(xiàng)(例如是否開(kāi)啟防盜鏈、是否允許瀏覽器直接訪問(wèn)、白名單域名等)寫(xiě)在 application.yml
中,并利用配置類映射到 Java 對(duì)象中。
3.1 配置文件示例
在 application.yml
中定義如下配置:
img-protect: enabled: true allowBrowser: false allowReferer: baidudu.com
3.2 映射配置類
利用 @ConfigurationProperties
將配置項(xiàng)映射到 Java 類中,方便后續(xù)使用:
@Component @ConfigurationProperties("img-protect") public class ImgProtectConfig { private boolean enabled; private boolean allowBrowser; private String allowReferer; // getter/setter 略 }
3.3 攔截器實(shí)現(xiàn)細(xì)節(jié)
在新版攔截器中,通過(guò)注入上述配置類,實(shí)現(xiàn)如下邏輯:
- 若防盜鏈功能未開(kāi)啟,則直接放行。
- 對(duì)圖片資源請(qǐng)求(通過(guò) URL 后綴判斷):
- 如果 Referer 為空且允許瀏覽器直接訪問(wèn)(allowBrowser 為 true),則放行;
- 如果 Referer 不為空,則調(diào)用輔助方法判斷 Referer 是否包含配置中允許的域名(允許多個(gè)域名,逗號(hào)分隔);
- 否則返回 403。
例如:
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!imgProtectConfig.getEnabled()){ return true; } String requestUrl = request.getRequestURL().toString(); if (requestUrl.endsWith(".jpg") || requestUrl.endsWith(".png") || requestUrl.endsWith(".jpeg")) { String referer = request.getHeader("Referer"); if (referer == null && imgProtectConfig.getAllowBrowser()){ return true; } else if (referer != null && isAllowedDomain(referer)) { return true; } else { response.sendError(HttpServletResponse.SC_FORBIDDEN); return false; } } return true; }
其中 isAllowedDomain
方法遍歷配置中允許的多個(gè)域名進(jìn)行比對(duì)。
4. 注意事項(xiàng)及局限性
雖然這種通過(guò)檢查 Referer 實(shí)現(xiàn)的防盜鏈功能在一般場(chǎng)景下能有效防止資源被盜用,但仍存在一些不足之處:
- Referer 偽造:惡意客戶端可以偽造 Referer 頭信息,繞過(guò)檢測(cè)。
- 漏報(bào)問(wèn)題:攻擊者可能利用 data URI 或 Base64 編碼等方式繞過(guò)檢查。
- 誤報(bào)問(wèn)題:部分合法用戶(例如使用隱私瀏覽器或代理服務(wù)器時(shí))可能因 Referer 不匹配而被誤攔截。
- 反向代理問(wèn)題:攻擊者可能利用反向代理手法,通過(guò) URL 路徑中加入白名單域名繞過(guò) contains 判斷。
因此,該方法只是基本防護(hù)手段,并不能保證絕對(duì)安全,實(shí)際應(yīng)用中可結(jié)合更嚴(yán)格的安全措施(如 Token 驗(yàn)證、Nginx 防盜鏈等)來(lái)共同提升防護(hù)效果。
5. 總結(jié)
本文展示了兩種基于 Spring Boot 實(shí)現(xiàn)圖片防盜鏈的方式:
- 簡(jiǎn)單寫(xiě)死配置的方式,直接在攔截器中判斷 Referer;
- 基于配置文件靈活配置的方式,通過(guò)
application.yml
配置防盜鏈參數(shù),并在攔截器中使用。
雖然這種方法能對(duì)一般情況下的盜鏈行為起到一定防護(hù)作用,但考慮到 Referer 可偽造等問(wèn)題,實(shí)際項(xiàng)目中還需根據(jù)具體場(chǎng)景綜合考慮更全面的安全策略。
到此這篇關(guān)于基于SpringBoot實(shí)現(xiàn)圖片防盜鏈的兩種方式的文章就介紹到這了,更多相關(guān)SpringBoot圖片防盜鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解Java運(yùn)行時(shí)數(shù)據(jù)區(qū)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java運(yùn)行時(shí)數(shù)據(jù)區(qū)的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-06-06java中json-diff簡(jiǎn)單使用及對(duì)象是否一致詳解
這篇文章主要為大家介紹了java中json-diff簡(jiǎn)單使用及對(duì)象是否一致對(duì)比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03java并發(fā)編程synchronized底層實(shí)現(xiàn)原理
這篇文章主要介紹了java并發(fā)編程synchronized底層實(shí)現(xiàn)原理2022-02-02JavaWeb 實(shí)現(xiàn)多個(gè)文件壓縮下載功能
文件下載時(shí),我們可能需要一次下載多個(gè)文件,批量下載文件時(shí),需要將多個(gè)文件打包為zip,然后再下載。本文給大家分享實(shí)現(xiàn)思路及具體實(shí)現(xiàn)代碼,對(duì)javaweb實(shí)現(xiàn)文件壓縮下載功能感興趣的朋友一起學(xué)習(xí)吧2017-07-07Java如何基于ProcessBuilder類調(diào)用外部程序
這篇文章主要介紹了Java如何基于ProcessBuilder類調(diào)用外部程序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Java 11 正式發(fā)布,這 8 個(gè)逆天新特性教你寫(xiě)出更牛的代碼
美國(guó)當(dāng)?shù)貢r(shí)間9月25日,Oracle 官方宣布 Java 11 (18.9 LTS) 正式發(fā)布,可在生產(chǎn)環(huán)境中使用!這是自 Java 8 后的首個(gè)長(zhǎng)期支持版本2018-09-09Java工具jsch.jar實(shí)現(xiàn)上傳下載
這篇文章主要為大家詳細(xì)介紹了Java操作ftp的一款工具,利用jsch.jar針對(duì)sftp的上傳下載工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12SpringBoot事件機(jī)制相關(guān)知識(shí)點(diǎn)匯總
這篇文章主要介紹了SpringBoot事件機(jī)制相關(guān)知識(shí)點(diǎn)匯總,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09