關於img 403 forbidden的一些思考


網頁中經常需要顯示圖片給用戶看,對網站本身來說有的圖片是從本地圖片服務器來的,但是一旦數量多了以后,磁盤空間又是一個問題。

所以有時就希望顯示其他網站的Image,直接把其他網站的圖片顯示在我的網站上。但並不是所有的外網Image 都能直接連接過來顯示。

很多情況下網站開發人員就會遇到 403 forbidden的問題。比如想顯示來自IMDB的一張圖片

<img src="http://ia.media-imdb.com/images/M/MV5BMjIwMjYyNjk4Nl5BMl5BanBnXkFtZTcwNzA4NDYwMw@@._V1_UY317_CR12,0,214,317_AL_.jpg" height="350" width="200">

本地localhost Debug的時候完全可以顯示,但是將網站部署到服務器后就會遇到這樣的錯誤

image

奇怪的是通過瀏覽器訪問圖片的連接,圖片就正常的顯示了出來。

這又是為什么?其實Referer是由瀏覽器自動加上的,但是也有例外比如

1. 直接通過瀏覽器訪問

2. 在web前段使用location.href 或者location.replace

3. 利用HTTPS等加密協議

這就是HotLinking 盜鏈問題, 可以通過配置網站Server 端來實現這種反盜鏈的行為。

 

為什么像IMDB這樣的網站要做 Anti HotLinking反盜鏈的事情呢?

版權的問題是一方面。

另一方面可以稱作Bandwidth Theft, 當用戶訪問IMDB頁面的時候,IMDB需要Bandwidth傳輸數據,而Bandwidth 是網站的成本之一。

好比誰也不願意陌生人偷偷的把電器插到你的插座,偷偷的用你的電,而你去負擔所有的費用。

 

如何配置Server實現Anti HotLinking 呢?

以Asp.net MVC 為例

可以給Controller 添加ActionFilter 或者添加處理AntiHotLinking 的 IHttpHandler

核心都是UrlReferrer

HttpRequest 有個字段 UrlReferrer:

image

 

該字段表示哪個Url  通過像上面Img Src的方式訪問了Server.

//訪問者的域
var refDomain = Request.UrlReferrer.Host;

//當前WebSite的域
var serverDomain = Request.Url.Host;

最后可以通過判斷 是否來自同一個域 來決定Anti HotLinking的策略

或者可以通過在web.config 中配置URLRewrite來實現

復制代碼
<rewrite>
<rules>
  <rule name="Anti HotLinking Rule for Image" enabled="true" stopProcessing="true">
  <match url=".*\.(gif|jpg|png)$" />
  <conditions>
    <add input="{HTTP_REFERER}" negate="true" pattern="^$" />
    <add input="{HTTP_REFERER}" negate="true" pattern="http://www.yourwebsite.com/.*" />
    <add input="{HTTP_REFERER}" negate="true" pattern="http://yourwebsite.com/.*" />
  </conditions>
  <action type="Rewrite" url="/images/anti-hotlinking.png" />
</rule>
</rules>
</rewrite>
復制代碼

 

如果網站用戶就是希望看到不能顯示的圖片或者視頻呢?

這里給大家推薦一個Chrome 插件 Anti-Anti-HotLinking

安裝后就能看到未能顯示的圖片。

對該插件我沒有仔細研究,有可能是通過Download來解決Hotlinking 問題的,也有可能是通過Chrome劫持Request 修改UrlReferer實現的。

 

對網站開發人員有什么解決辦法嗎?

1. 將外網的Image在Server端下載 再轉換成 base64 最后傳輸給img 標簽。

復制代碼
        public static string ImageToBase64(Stream imageStream, ImageFormat format)
        {
            using (System.Drawing.Image image = System.Drawing.Image.FromStream(imageStream))
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    image.Save(stream, format);

                    var result = System.Convert.ToBase64String(stream.ToArray());
                    return result;
                }
            }
        }
復制代碼
<img src="data:image/png;base64,這里存放轉換成base64的字符串 />

 2. 利用RefererKiller這個JavaScript插件 繞過UrlReferer

  ReferrerKiller.imageHtml("fakeweb/fakeimage.png"); 返回能夠顯示的img的Html字符串

  ReferrerKiller.imageHtml("fakeweb/fakeimage.png"); 返回能夠顯示的img的DOM節點

  其實這兩個函數是同一個東西,可以撿方便的用。

  這種方式解決HotLinking問題其實原理很簡單,在web中 比如<script src="differentDomain/fake.js"> </script>

  加載js 是沒有跨域訪問的問題。

  ReferrerKiller 就動態生成一個iframe,並在iframe內加入img標簽。利用src加載的特性把代碼放到src中,就可以去掉Referer。

  所以ReferrerKiller.imageHtml返回的是一個能顯示圖片的iframe。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM