有些產品爲了防止本身的產品被盜鏈訪問,會採用反盜鏈措施,如封閉型生態的音樂網站和視頻網站,他們已經爲了版權付費,天然不但願你無償使用他們的資源。但由於不少人專門研究盜鏈,所以咱們也須要了解下盜鏈、反盜鏈和逃避反盜鏈的原理。php
引用百度百科對盜鏈的定義:css
盜鏈是指服務提供商本身不提供服務的內容,經過技術手段繞過其它有利益的最終用戶界面(如廣告),直接在本身的網站上向最終用戶提供其它服務提供商的服務內容,騙取最終用戶的瀏覽和點擊率。受益者不提供資源或提供不多的資源,而真正的服務提供商卻得不到任何的收益。
咱們知道,網站提供服務是向服務端請求一個html
文件,這個文件中包含有css/js
文件,也包含img/video
標籤,這些靜態資源會在html
文件加載時,依次的發起請求並填充在指定位置上,從而完成整個頁面的加載。html
所以只要拿到這個圖片的URL
並嵌入咱們本身的html
文件中,就能在咱們的網站上訪問,因爲資源是不一樣的HTTP
請求獨立訪問的,所以咱們也能過濾源站的html
文件。這就是最簡單的盜鏈。前端
危害:在用戶訪問時,並無在訪問被盜鏈網站,可是依然會佔用該網站的帶寬資源,而帶寬是要給運營商付費的。同時,該網站的廣告、周邊、宣傳等資源並不會被用戶訪問到。nginx
分佈式盜鏈比較複雜,須要在服務端部署專門的程序,並不針對單個網站或單個url
,而是對全網的全部有用的資源進行盜取,並存儲在本身的數據庫中,並在用戶實際訪問時,徹底轉換爲本身的流量。ajax
危害:本身經過勞動、金錢、版權付費獲得的資源,被盜鏈網站無償使用,如網店攝影圖、期刊、電視劇等。並所以致使本身的會員、服務沒法實現盈利。數據庫
咱們瞭解了盜鏈對源站的危害後,天然要經過一些手段來阻止這種行爲維護本身的利益。segmentfault
這是最簡單的方法,經過後端程序批量對圖片等資源加上水印,這樣在盜鏈的同時,也在爲本身的網站作宣傳,有時甚至會主動尋求這種盜鏈。後端
由於盜鏈是經過指定的url,這個url
中必定包含該資源的路徑和名稱,所以經過不按期的更改文件或目錄的名稱,可以快速避免盜鏈,但也會致使正在下載的資源被中斷。跨域
在http
請求的頭部信息中,有一個字段:referer
,它表明這個請求是從哪一個頁面發起的,若是是單獨在頁面中打開或者服務端請求的,則這個字段爲空。所以咱們能夠經過referer
這個字段的值作限制,若是是本身承認的頁面,則返回資源,不然,禁止該請求。可是因爲每次都要打開一個白名單的文件作url
匹配,所以會下降性能。
在客戶端經過將用戶認證的信息和資源的名稱進行組合後加密,將加密的字符串做爲url
的參數發起請求,在服務端進行解密並認證經過後,纔會返回請求的資源。這個方式主要用於防範分佈式盜鏈。
上面的3種反盜鏈方式,咱們經常使用的是第三種,經過referer
屬性來完成反盜鏈,今天也主要分享這一種方法的反盜鏈與防反盜鏈。
這種限制須要消耗服務端計算資源,所以不如Nginx
限制經常使用。
$from = parse_url($_SERVER['HTTP_REFERER']); if ($from['host']!='xxx.com' && $from['host']!='www.xxx.com') { die('你丫在盜鏈'); }
Nginx
限制經過修改nginx
配置文件能夠作到,修改完成後記得重啓nginx
:
// 這裏指定須要防盜鏈的資源,如gif/jpg等 location ~* \.(gif|jpg|png|jpeg)$ { // 設置資源的過時時間 expires 30d; // 設置合法的引用頁,也就是防盜鏈的白名單; // none blocked保證用戶在新頁面打開時依然可以打開,若是不但願用戶可以保存刪掉這兩項 valid_referers none blocked *.hugao8.com *.baidu.com *.google.com; // 對於非法的引用頁,能夠重寫圖片,也能夠直接返回403或404頁面 if ($invalid_referer) { rewrite ^/http://www.it300.com/static/images/404.jpg; #return 404; } }
Referer-Policy
Referer
首部包含了當前請求頁面的來源頁面的地址,即表示當前頁面是經過此來源頁面裏的連接進入的。服務端通常使用Referer
首部識別訪問來源,可能會以此進行統計分析、日誌記錄以及緩存優化等。
Referer
屬性出如今請求頭中,也在請求頭中被設置,可是在瀏覽器的安全策略裏,該值沒法被js
所指定:
$.ajax({ url: 'http://www.baidu.com', beforeSend(xhr) { // 在發送ajax請求前設置header頭部 xhr.setRequestHeader("Referer", "http://translate.google.com/"); xhr.setRequestHeader("User-Agent", "stagefright/1.2 (Linux;Android 5.0)"); }, success(data) { console.log(data); }, error(err) { console.log(err); } });
然而瀏覽器會報錯:
那麼Referer
是怎麼被自動設置的呢?這個得看Referer-Policy屬性是怎麼定義的:
no-referrer
: 整個 Referer 首部會被移除。訪問來源信息不隨着請求一塊兒發送。no-referrer-when-downgrade
(默認值): 在沒有指定任何策略的狀況下用戶代理的默認行爲。在同等安全級別的狀況下,引用頁面的地址會被髮送(HTTPS->HTTPS),可是在降級的狀況下不會被髮送 (HTTPS->HTTP)。origin
: 在任何狀況下,僅發送文件的源做爲引用地址。例如 https://example.com/page.html 會將 https://example.com/ 做爲引用地址。origin-when-cross-origin
: 對於同源的請求,會發送完整的URL做爲引用地址,可是對於非同源請求僅發送文件的源。same-origin
: 對於同源的請求會發送引用地址,可是對於非同源請求則不發送引用地址信息。strict-origin
: 在同等安全級別的狀況下,發送文件的源做爲引用地址(HTTPS->HTTPS),可是在降級的狀況下不會發送 (HTTPS->HTTP)。strict-origin-when-cross-origin
: 對於同源的請求,會發送完整的URL做爲引用地址;在同等安全級別的狀況下,發送文件的源做爲引用地址(HTTPS->HTTPS);在降級的狀況下不發送此首部 (HTTPS->HTTP)。unsafe-url
: 不管是同源請求仍是非同源請求,都發送完整的 URL(移除參數信息以後)做爲引用地址。這個值能夠經過三種方式來設置:
<meta name="referrer" content="origin"> <a href="http://example.com" referrerpolicy="origin"> <a href="http://example.com" rel="noreferrer">
前端JS
不能在頭部設置Referer
字段,和跨域同樣是由於瀏覽器的安全策略,那麼一樣的在服務端進行請求就不會有這些限制,咱們在服務端請求時就能夠自由的修改Referer
字段。
咱們經過簡單的PHP
例子來完成這個功能:
<?php $url = 'http://t11.baidu.com/it/u=3008889497,862090385&fm=77'; $refer = 'https://www.baidu.com'; $ch = curl_init(); //以url的形式 進行請求 curl_setopt($ch, CURLOPT_URL, $url); //以文件流的形式 進行返回 不直接輸出到瀏覽器 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //瀏覽器發起請求 超時設置 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); //僞造來源地址 curl_setopt ($ch, CURLOPT_REFERER, $refer); $file = curl_exec($ch); curl_close($ch); header('Content-Type: text/html'); // 對圖片進行base64編碼,而後返回給前端展現 $file = base64_encode($file); echo "<img src='data:image/jpeg;base64,{$file}' />"; ?>
咱們第一次請求註釋了僞造來源地址
這一行,第二次請求不註釋這一行,這樣能夠驗證執行結果:
盜鏈和反盜鏈是一個對立面,技術不斷升級,最終的目標也是爲了開放資源和保護知識產權。在互聯網生態裏,咱們經過反盜鏈保護咱們的利益,也使用防反盜鏈的這種方式來擴大咱們的內容,不管站在哪一方,都須要作到知己知彼。