閱讀70 返回首頁    go 小米淨水器


防盜鏈__存儲空間管理_最佳實踐_對象存儲 OSS-阿裏雲

背景

A是網站站長,在A的網站的網頁裏有一些圖片和音頻視頻的鏈接,這些靜態資源都保存在阿裏雲對象存儲OSS上。以圖片為例子,A在OSS上存放的URL為https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png。OSS資源外鏈地址見OSS 地址,這樣的URL(不帶簽名)要求用戶的Bucket權限為公開讀權限。

B是另一個網站的站長,B在未經A允許的情況下,偷偷使用A的網站的圖片資源,放置在自己網站的網頁中,通過這種方法盜取空間和流量。在這樣的情況下,第三方網站用戶看到的是B的網站,網站用戶不知道也不關心網站裏的圖片是來自於哪裏。由於OSS是按照使用量來收費的,這樣用戶A在沒有獲取任何收益的情況下,反而承擔了資源使用費用。

本文就是介紹類似A這樣的用戶將資源存放在OSS上後,如何設置防盜鏈來避免這樣情況的發生。本文適用那些在網頁中使用了OSS資源作為外鏈的用戶。

實現方法

目前OSS提供的防盜鏈的實現方法主要有兩種:

  • 設置Referer。控製台、SDK都可以操作,適合不想寫代碼的用戶,也適合喜歡開發的用戶。
  • 簽名URL,適合喜歡開發的用戶。

本文會給一個控製台設置Referer防盜鏈的具體事例,也會基於PHP SDK給一個動態生成簽名URL防盜鏈的示例。

設置Referer

這裏主要說明Referer是什麼,OSS如何利用Referer做防盜鏈。

Referer是什麼

Referer是HTTP Header的一部分,當瀏覽器向網站Web服務器發送請求的時候,一般會帶上Referer,告訴服務器此次請求是從哪個頁麵鏈接過來的。以上麵的例子來說,假如用戶B的網站叫userdomain-steal,想盜鏈用戶A的圖片鏈接https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png。A的網站域名為userdomain

假設盜鏈網站userdomain-steal的網頁如下:

  1. <html>
  2. <p>This is a test</p>
  3. <img src="https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png" />
  4. </html>

假設源站為userdomain的網頁如下:

  1. <html>
  2. <p>This is my test link from OSS URL</p>
  3. <img src="https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png" />
  4. </html>
  • 當互聯網用戶用瀏覽器訪問B的網站頁麵https://userdomain-steal/index.html,網頁裏鏈接是A的網站的圖片。由於從一個域名(userdomain-steal)請求跳到了另一個域名(oss-cn-hangzhou.aliyuncs.com),瀏覽器就會在HTTP請求的Header中帶上Referer,如圖所示:

    可以看到瀏覽器在HTTP請求中的Referer為https://userdomain-steal/index.html。本文主要是使用chrome的開發者模式來查看網頁請求的,如圖:

  • 同樣瀏覽器訪問https://userdomain/error.html,也可以看到瀏覽器的Referer為https://userdomain/error.html

  • 如果瀏覽器直接輸入地址,可以看到,請求中的Referer為空。

如果A沒有在OSS進行任何Referer相關設置,以上三種情況都是可以訪問用戶A的圖片鏈接。

OSS通過Referer防盜鏈的原理

通過上麵的例子可以看到,瀏覽器在請求OSS資源的時候,如果發生頁麵跳轉,瀏覽器會在請求中帶入Referer,此時Referer的值為上一頁麵的URL,有的時候Referer也會為空。

針對這兩種情況,OSS的Referer功能提供兩種選擇:

  • 設置是否允許空Referer訪問。不能單獨設置,需要配合Referer白名單一起使用。
  • 設置Referer白名單。

細節分析如下:

  • 用戶隻有通過簽名URL或者匿名訪問object時,才會做防盜鏈驗證。請求的Header中有“Authorization”字段的,不會做防盜鏈驗證。
  • 一個Bucket可以支持多個Referer參數。
  • Referer參數支持通配符“*”和“?”。
  • 用戶可以設置允許空Referer的請求訪問。
  • 白名單為空時,不會檢查Referer字段是否為空(不然所有的請求都會被拒絕,因為空Referer會被拒絕,對於非空Referer OSS在Referer白名單裏也找不到)。
  • 白名單不為空,且設置了”不允許Referer字段為空”的規則。則隻有Referer屬於白名單的請求被允許,其他請求(包括Referer為空的請求)會被拒絕。
  • 白名單不為空,但設置了”允許Referer字段為空”的規則。則Referer為空的請求和符合白名單的請求會被允許,其他請求都會被拒絕。
  • Bucket的三種權限(private,public-read,public-read-write)都會檢查Referer字段。

通配符詳解:

  • 星號“*”:可以使用星號代替0個或多個字符。如果正在查找以AEW開頭的一個文件,但不記得文件名其餘部分,可以輸入AEW,查找以AEW開頭的所有文件類型的文件,如AEWT.txt、AEWU.EXE、AEWI.dll等。要縮小範圍可以輸入AEW.txt,查找以AEW開頭的所有文件類型並.txt為擴展名的文件如AEWIP.txt、AEWDF.txt。
  • 問號“?”:可以使用問號代替一個字符。如果輸入love?,查找以love開頭的一個字符結尾文件類型的文件,如lovey、lovei等。要縮小範圍可以輸入love?.doc,查找以love開頭的一個字符結尾文件類型並.doc為擴展名的文件如lovey.doc、loveh.doc。

不同的Referer設置和防盜鏈效果

來看看Referer設置的效果:

1 隻設置”不允許refer為空”

從控製台中來設置不允許refer為空,如圖所示:

直接訪問:發現可以訪問,是防盜鏈失效了嗎?不是的,因為”白名單為空時,不會檢查Referer字段是否為空”,所以白名單為空的時候,這個設置無效。因此需要設置Referer白名單。

2 設置”不允許refer為空”的同時也設置Referer白名單

從前麵例子中我們可以看到在瀏覽器的請求中Referer為當前頁麵的URL,所以需要知道網站會從哪幾個URL跳轉過來,然後進行配置。

Referfer白名單的設置規則:

  • 例子中的Referer為https://userdomain/error.html,所以Referer白名單可以設置為https://userdomain/error.html,但由於OSS的Referer檢查是通過前綴匹配的,假如有其他網頁比如https://userdomain/index.html就訪問不了,所以Referer白名單可以配置成https://userdomain/
  • 假如還有其他域名比如https://img.userdomain/index.html也需要訪問,那麼Referer白名單應該加上https://*.userdomain/

這裏兩個都配置,如圖所示:

做測試可以得到如下結果:

瀏覽器輸入 預期 結果
https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png 直接訪問,Referer為空,預期:不允許空Referer的請求,返回403 符合預期
https://userdomain/error.html 請求來自於源站,預期:訪問成功 符合預期
https://userdomain-steal/index.html 請求來自於盜鏈網站。預期:OSS返回403,防盜鏈成功。 符合預期
https://img.userdomain/error.html 請求來自於源站三級域名 符合預期

注意:

  • 測試中提到的域名都是為了測試而假設的,和您實際的域名不一樣,請注意區分。
  • 如果Referer白名單隻有https://userdomain/,瀏覽器模擬三級域名訪問https://img.userdomain/error.html的時候,三級域名無法匹配Referer白名單,OSS就會返回403。
3 設置”允許refer為空”的同時也設置Referer白名單

Referer白名單有https://*.userdomain/https://userdomain。如圖所示:

做測試可以得到如下結果:

瀏覽器輸入 預期 結果
https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png 直接訪問,Referer為空,預期:訪問成功 符合預期
https://userdomain/error.html 請求來自於源站,預期:訪問成功 符合預期
https://userdomain-steal/index.html 請求來自於盜鏈網站。預期:OSS返回403,防盜鏈成功。 符合預期
https://img.userdomain/error.html 請求來自於源站三級域名 符合預期

如何在OSS裏設置Referer

功能使用參考:

Referer防盜鏈的缺點

Referer防盜鏈的優點是設置簡單,控製台即可操作。最大的缺點就是無法防止惡意偽造Referer,如果盜鏈是通過應用程序模擬HTTP請求,偽造Referer,則會繞過用戶防盜鏈設置。如果對防盜鏈有更高要求的可以參考下麵簽名URL防盜鏈的描述。

簽名URL

簽名URL的原理和實現方法見OSS開發人員指南授權第三方下載。簽名URL的實現步驟如下:

  1. 將Bucket的權限設置為私有讀。
  2. 根據期望的超時時間(簽名URL失效的時間)生成簽名。

具體實現

  1. 安裝PHP最新代碼,參考PHP SDK文檔
  2. 實現生成簽名URL並將其放在網頁中,作為外鏈使用的簡單示例如下:

    1. <?php
    2. require 'vendor/autoload.php';
    3. #最新PHP提供的自動加載
    4. use OSSOssClient;
    5. #表示命名空間的使用
    6. $accessKeyId="a5etodit71tlznjt3pdx7lch";
    7. #AccessKeyId,需要使用用戶自己的
    8. $accessKeySecret="secret_key";
    9. #AccessKeySecret,需要用用戶自己的
    10. $endpoint="oss-cn-hangzhou.aliyuncs.com";
    11. #Endpoint,根據Bucket創建的區域來選擇,本文中是杭州
    12. $bucket = 'referer-test';
    13. #Bucket,需要用用戶自己的
    14. $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
    15. $object = "aliyun-logo.png";
    16. #需要簽名的Object
    17. $timeout = 300;
    18. #期望鏈接失效的時間,這裏表示從代碼運行到這一行開始的當前時間往後300秒
    19. $signedUrl = $ossClient->signUrl($bucket, $object, $timeout); #簽名URL實現的函數
    20. $img= $signedUrl;
    21. #將簽名URL動態放到圖片資源中並打印出來
    22. $my_html = "<html>";
    23. $my_html .= "<img src="".$img. "" />";
    24. $my_html .= "<p>".$img."</p>";
    25. $my_html .= "</html>";
    26. echo $my_html;
    27. ?>
  3. 通過瀏覽器訪問多請求幾次會發現簽名的URL會變,這是正常的。主要是因為過期時間的改變導致的。這個過期時間是鏈接失效的時間,是以Unix time的形式展示的。例如:Expires=1448991693,可以將這個時間轉換成本地時間。在Linux下的命令為date -d@1448991693,也可以在網絡上找工具自行轉換。

特別說明

簽名URL可以和Referer白名單功能一起使用。

如果簽名URL失效的時間限製在分鍾內,盜鏈用戶即使偽造了Referer也必須拿到簽名的URL,且必須在有效的時間內才能盜鏈成功。相比隻使用Referer來說,增加了盜鏈的難度。也就是說簽名URL配合Referer白名單功能,可以增加防盜鏈的效果。

防盜鏈總結

基於OSS的防盜鏈最佳實踐點如下:

  • 使用三級域名URL,例如referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png,安全性比綁定二級域名更高。三級域名方式能夠提供Bucket級別的清洗和隔離,能夠應對被盜鏈後的流量暴漲的情況,也能避免不同Bucket間的互相影響,最終提高業務可用性。
  • 如果使用自定義域名作為連接,CNAME也請綁定到三級域名,規則是bucket + endpoint。假如您的bucket名為test,三級域名則為test.oss-cn-hangzhou.aliyuncs.com
  • 對Bucket設定盡可能嚴格的權限類別。例如提供公網服務的Bucket設置為public-read或private,禁止設置為public-read-write。Bucket權限參見訪問控製
  • 對訪問來源進行驗證,根據需要設置合適的Referer白名單。
  • 如果需要更嚴格的防盜鏈方案,請參考簽名的URL方案。
  • 記錄Bucket訪問日誌,能夠及時發現盜鏈活動和驗證防盜鏈方案的有效性。 訪問日誌參見 設置訪問日誌記錄

常見問題及解決方案

  • 在OSS控製台設置了防盜鏈,一直不生效,但頁麵可以防而播放器不可以,請問為什麼?怎麼解決?

    目前設置防盜鏈不生效的主要問題集中於視頻和音頻文件,在使用諸如Windows Media Player、Flash Player等播放器後,在請求OSS資源的時候傳遞的Referer為空,這就造成防盜鏈的失效,不僅僅把別人防住了,也把自己給防住了。針對這種情況,可以參考上麵提到的簽名URL防盜鏈的方法。

  • Referer是什麼?怎樣才會帶上?如果遇到HTTPS怎麼辦,不需要添加別的了嗎,比如逗號之類的?

    Referer是HTTP協議中的請求頭,在跨頁麵訪問的時候會帶上。需要看看瀏覽器請求的Referer是https://還是https://,一般是https://

  • 如何生成簽名URL?AccessKeySecret放在客戶端裏的安全性?

    簽名URL的方法參見各個SDK文檔。AccessKeySecret這種不建議直接放在客戶端,RAM提供了STS服務可以解決這個問題。也可以參考RAM和STS指南

  • 例如要寫a.baidu.comb.baidu.com,這兩個用通配符(*,?) 如何寫?

    可以寫成https://*.baidu.com,對於這種單字符的也可以寫成https://?.baidu.com

  • *.domain.com 可以匹配二級域名,但無法匹配 domain.com,另外添加一行 domain.com 也沒效果,如何配置?

    注意一般的referer中會帶http這樣的參數,可以通過chrome的開發者模式觀察下請求的Referer是什麼,然後再具體設置。這裏可能是忘了寫https://,應該為https://domain.com

  • 如果防盜鏈沒有生效怎麼辦?

    推薦使用chrome來查看。打開開發者模式,點擊網頁,查看HTTP請求中的Referer具體值是什麼,對應在OSS中設置的Referer,是否能匹配上。如果還是解決不了,請提工單。

最後更新:2016-11-23 16:04:09

  上一篇:go 跨域資源共享(CORS)__存儲空間管理_最佳實踐_對象存儲 OSS-阿裏雲
  下一篇:go 權限管理概述__權限管理_最佳實踐_對象存儲 OSS-阿裏雲