使用HTTP?Referer實(shí)現(xiàn)圖片防盜圖文示例詳解
前言
上周突然發(fā)現(xiàn)自己的自己站點(diǎn)的圖片全都403了,之前還是好好的,圖片咋就全都訪(fǎng)問(wèn)不了呢?由于我每次發(fā)文章都是先發(fā)了掘金,然后再?gòu)木蚪鹂截惖轿易约旱恼军c(diǎn),這樣我就不用在自己的站點(diǎn)去上傳圖片了,非常方便。
啥也沒(méi)干,圖片咋就403了呢?估計(jì)又是整了什么開(kāi)源節(jié)流,降本增效吧,說(shuō)白了就是大家都用他站點(diǎn)的圖片導(dǎo)致流量費(fèi)用蹭蹭蹭的往上漲,人家肯定不愿意了,這下給圖片都加上防盜了,非自己的站點(diǎn)全都給你返回403.
防盜原理
是不是很好奇這些圖片防盜是怎么做的?
我們可以自己來(lái)實(shí)現(xiàn)一下這個(gè)場(chǎng)景:不受信任的域名訪(fǎng)問(wèn)我服務(wù)器上的圖片資源全都返回403
準(zhǔn)備幾個(gè)域名
這里沒(méi)有域名也不用擔(dān)心,我們可以直接本地模擬就行了,比如我這里使用SwitchHosts
給本地添加的三個(gè)域名并且都指向我們的本地IP
這樣的話(huà)這三個(gè)域名都能夠訪(fǎng)問(wèn)我們的本地服務(wù)了。
服務(wù)端邏輯
靜態(tài)資源目錄
這里就用之前的nest
服務(wù)來(lái)做演示,之前我們?cè)谶@個(gè)服務(wù)上指定了靜態(tài)資源目錄
app.useStaticAssets(join(__dirname, '../static'), { prefix: '/static', }); // 靜態(tài)資源
前端訪(fǎng)問(wèn)圖片
<img class="my_img" src="http://nanjiu.com:3000/static/sy.jpg" />
這里是使用nanjiu.com
代理域名來(lái)訪(fǎng)問(wèn)的,圖片能夠正常訪(fǎng)問(wèn)
防盜中間件
這里我們可以來(lái)實(shí)現(xiàn)一個(gè)全局中間件用來(lái)處理圖片的訪(fǎng)問(wèn),當(dāng)訪(fǎng)問(wèn)域名不在我們信任的白名單內(nèi)直接給他返回403
// 白名單 const whiteList = ['nanjiu.com', 'fenanjiu.com'] // 圖片防盜中間件 function imgMiddleware(req, res, next) { console.log('--req', req.headers) // 獲取資源類(lèi)型 const type = req.headers.accept || '' if(!type.includes('image')) { // 不是圖片資源,直接放行 next() return } const referer = req.headers.referer || '' // 獲取referer的域名 const { hostname } = url.parse(referer, true) if(referer && whiteList.includes(hostname) || !referer) { // 訪(fǎng)問(wèn)域名在白名單內(nèi),放行 !referer表示直接訪(fǎng)問(wèn)圖片(比如瀏覽器地址欄輸入圖片地址) res.status(200) next() }else { // 訪(fǎng)問(wèn)域名不在白名單內(nèi),返回403 res.status(403) res.send('逮到你了,又來(lái)偷我圖片是吧!') } }
這里需要注意的是,全局中間件在使用時(shí)一定要在useStaticAssets
之前
async function bootstrap() { const app = await NestFactory.create<NestExpressApplication>(AppModule); app.setGlobalPrefix('api'); // 全局路由前綴 app.use(cors()); // 允許跨域 app.use(json({ limit: '10mb' })); // 允許上傳大文件 app.use(urlencoded({ extended: true, limit: '10mb' })); // 允許上傳大文件 app.use(imgMiddleware) // 圖片防盜中間件 app.useStaticAssets(join(__dirname, '../static'), { prefix: '/static', }); // 靜態(tài)資源 await app.listen(3000); console.log(`Application is running on: ${await app.getUrl()}`); } bootstrap();
這上面的代碼中我們可以看到,現(xiàn)在受信任的域名就只有nanjiu.com
和fenanjiu.com
當(dāng)前端頁(yè)面使用sy.com
這個(gè)域名去訪(fǎng)問(wèn)nanjiu.com
域名下的圖片時(shí),此時(shí)應(yīng)該是會(huì)進(jìn)入防盜邏輯,返回403
并且送他一句
Referer
從上面我們實(shí)現(xiàn)的防盜原理來(lái)看,這其中最關(guān)鍵的就是referer
,那么這個(gè)referer
到底是什么呢?為什么可以用它來(lái)做圖片防盜
Referer是什么
MDN解釋如下:
Referer
請(qǐng)求頭包含了當(dāng)前請(qǐng)求頁(yè)面的來(lái)源頁(yè)面的地址,即表示當(dāng)前頁(yè)面是通過(guò)此來(lái)源頁(yè)面里的鏈接進(jìn)入的。服務(wù)端一般使用 Referer
請(qǐng)求頭識(shí)別訪(fǎng)問(wèn)來(lái)源,可能會(huì)以此進(jìn)行統(tǒng)計(jì)分析、日志記錄以及緩存優(yōu)化等。
從這里我們就大概能知道圖片防盜的原理了,服務(wù)端可以通過(guò)請(qǐng)求頭中的Referer
來(lái)識(shí)別訪(fǎng)問(wèn)來(lái)源,然后判斷應(yīng)不應(yīng)該給你返回圖片
Referer
這個(gè)單詞實(shí)際上是Referrer
的錯(cuò)誤拼寫(xiě),這其實(shí)是個(gè)歷史原因,在早期 HTTP 規(guī)范當(dāng)中就存在的拼寫(xiě)錯(cuò)誤,后面為了向下兼容,所以將錯(cuò)就錯(cuò)。
拼寫(xiě)錯(cuò)誤只有 Request Headers
的 Referer
,在其他地方比如General Headers
、 JavaScript
及 DOM
上,都是正確的拼寫(xiě)。
Referrer-Policy
Referrer-Policy
首部用來(lái)監(jiān)管哪些訪(fǎng)問(wèn)來(lái)源信息——會(huì)在 Referer 中發(fā)送——應(yīng)該被包含在生成的請(qǐng)求當(dāng)中。
它其實(shí)是用來(lái)控制 Referer 返回的具體內(nèi)容的
它有以下屬性值:
- no-referrer: 整個(gè) Referer 首部會(huì)被移除。訪(fǎng)問(wèn)來(lái)源信息不隨著請(qǐng)求一起發(fā)送。
- no-referrer-when-downgrade(默認(rèn)值): 在沒(méi)有指定任何策略的情況下用戶(hù)代理的默認(rèn)行為。在同等安全級(jí)別的情況下,引用頁(yè)面的地址會(huì)被發(fā)送 (HTTPS->HTTPS),但是在降級(jí)的情況下不會(huì)被發(fā)送 (HTTPS->HTTP)。
- origin: 在任何情況下,僅發(fā)送文件的源作為引用地址。例如
https://example.com/page.html
會(huì)將https://example.com/ 作為引用地址
。 - origin-when-cross-origin: 對(duì)于同源的請(qǐng)求,會(huì)發(fā)送完整的 URL 作為引用地址,但是對(duì)于非同源請(qǐng)求僅發(fā)送文件的源。
- same-origin: 對(duì)于同源的請(qǐng)求會(huì)發(fā)送引用地址,但是對(duì)于非同源請(qǐng)求則不發(fā)送引用地址信息。
- strict-origin: 在同等安全級(jí)別的情況下,發(fā)送文件的源作為引用地址 (HTTPS->HTTPS),但是在降級(jí)的情況下不會(huì)發(fā)送 (HTTPS->HTTP)。
- strict-origin-when-cross-origin: 對(duì)于同源的請(qǐng)求,會(huì)發(fā)送完整的 URL 作為引用地址;在同等安全級(jí)別的情況下,發(fā)送文件的源作為引用地址 (HTTPS->HTTPS);在降級(jí)的情況下不發(fā)送此首部 (HTTPS->HTTP)。
- unsafe-url: 無(wú)論是同源請(qǐng)求還是非同源請(qǐng)求,都發(fā)送完整的 URL(移除參數(shù)信息之后)作為引用地址。
這么多referrer
策略,我們?cè)趺词褂媚兀?/p>
meta標(biāo)簽使用
我們可以用一個(gè) name 為 referrer
的meta
元素為整個(gè)文檔設(shè)置 referrer
策略
<meta name="referrer" content="no-referrer">
我的個(gè)人站點(diǎn)就是使用該方法來(lái)解決圖片訪(fǎng)問(wèn)403問(wèn)題的,但需要注意的是,如果你為頁(yè)面設(shè)置了no-referrer
策略會(huì)導(dǎo)致頁(yè)面上所有的請(qǐng)求都不會(huì)發(fā)送referer
,使用時(shí)需要自己權(quán)衡利弊。
rel屬性
可以在a
、area
、link
標(biāo)簽上通過(guò)rel
屬性來(lái)單獨(dú)指定referrer
的策略
<a href="xxx" rel="external nofollow" rel="noreferrer">新地址</a>
referrerpolicy屬性
可以在a
、area
、link
、img
、iframe
、script
標(biāo)簽上通過(guò)referrerpolicy
屬性來(lái)單獨(dú)指定referrer
策略
<img class="my_img" referrerpolicy="no-referrer" src="http://nanjiu.com:3000/static/sy.jpg" />
比如上面例子中的這張圖片我們加上referrerpolicy="no-referrer"
再去訪(fǎng)問(wèn),頁(yè)面還是在sy.com
這個(gè)域名下面
可以看到請(qǐng)求頭中沒(méi)有攜帶referer
,所以它就能夠躲過(guò)圖片防盜邏輯。
Headers請(qǐng)求頭
也可以更改 HTTP 頭信息中的 Referer-Policy 值。比如你使用的是 Nginx,則可以設(shè)置 add\_headers 設(shè)置請(qǐng)求頭。
add_header Referrer-Policy "no-referrer";
Headers 請(qǐng)求頭和其它頁(yè)面元素屬性同時(shí)存在時(shí),確定元素的有效策略時(shí)的優(yōu)先順序是:
- 元素級(jí)策略
- 頁(yè)面級(jí)策略
- 瀏覽器默認(rèn)
以上就是使用HTTP Referer實(shí)現(xiàn)圖片防盜圖文示例詳解的詳細(xì)內(nèi)容,更多關(guān)于HTTP Referer圖片防盜的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript數(shù)據(jù)類(lèi)型對(duì)函數(shù)式編程的影響示例解析
這篇文章主要為大家介紹了JavaScript數(shù)據(jù)類(lèi)型對(duì)函數(shù)式編程的影響示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02ECMAScript 6對(duì)象的擴(kuò)展實(shí)現(xiàn)示例
這篇文章主要為大家介紹了ECMAScript 6對(duì)象的擴(kuò)展實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08詳解微信小程序 通過(guò)控制CSS實(shí)現(xiàn)view隱藏與顯示
這篇文章主要介紹了微信小程序 通過(guò)控制CSS實(shí)現(xiàn)view隱藏與顯示的相關(guān)資料,需要的朋友可以參考下2017-05-05微信小程序 <swiper-item>標(biāo)簽傳入數(shù)據(jù)
這篇文章主要介紹了微信小程序 <swiper-item>標(biāo)簽傳入數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2017-05-05微信小程序 wx.uploadFile在安卓手機(jī)上面the same task is working問(wèn)題解決
這篇文章主要介紹了微信小程序 wx.uploadFile在安卓手機(jī)上面the same task is working問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2016-12-12前端通過(guò)JavaScript創(chuàng)建修改CAD圖形詳情
這篇文章介紹JavaScript創(chuàng)建修改CAD圖形,創(chuàng)建修改CAD圖形,一般是基于A(yíng)utoCAD進(jìn)行二次開(kāi)發(fā),ObjectARX是AutoDesk公司針對(duì)AutoCAD平臺(tái)上的二次開(kāi)發(fā)而推出的一個(gè)開(kāi)發(fā)軟件包,它提供了以C++為基礎(chǔ)的面向?qū)ο蟮拈_(kāi)發(fā)環(huán)境及應(yīng)用程序接口,能真正快速的訪(fǎng)問(wèn)AutoCAD圖形數(shù)據(jù)庫(kù)2021-10-10