
1.問(wèn)題
網(wǎng)頁(yè)中經(jīng)常需要顯示圖片給用戶看,對(duì)網(wǎng)站本身來(lái)說(shuō)有的圖片是從本地圖片服務(wù)器來(lái)的,但是一旦數(shù)量多了以后,磁盤空間又是一個(gè)問(wèn)題。
有時(shí)就希望顯示其他網(wǎng)站的
Image,直接把其他網(wǎng)站的圖片顯示在我的網(wǎng)站上。但并不是所有的外網(wǎng)Image都能直接連接過(guò)來(lái)顯示。
但是很多情況下網(wǎng)站開發(fā)人員就會(huì)遇到 403 forbidden 的問(wèn)題。比如想顯示來(lái)自簡(jiǎn)書的一張圖片
<img src="https://upload-images.jianshu.io/upload_images/15521290-b56cd3b1bc721cf9.png">
本地localhost Debug的時(shí)候完全可以顯示,但是將網(wǎng)站部署到服務(wù)器后就會(huì)遇到這樣的錯(cuò)誤

2.原因
為什么網(wǎng)站要做 Anti HotLinking反盜鏈的事情呢
版權(quán)的問(wèn)題
Bandwidth Theft
當(dāng)用戶訪問(wèn)IMDB 頁(yè)面的時(shí)候,IMDB 需要Bandwidth 傳輸數(shù)據(jù),而Bandwidth 是網(wǎng)站的成本之一,好比誰(shuí)也不愿意陌生人偷偷的把電器插到你的插座,偷偷的用你的電,而你去負(fù)擔(dān)所有的費(fèi)用。
3.解決
針對(duì)web 開發(fā)人員有以下解決辦法:
- 將外網(wǎng)的
Image在Server端下載 再轉(zhuǎn)換成base64最后傳輸給img 標(biāo)簽
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,這里存放轉(zhuǎn)換成base64的字符串 />
- 利用RefererKiller這個(gè)JavaScript插件 繞過(guò)
UrlReferer
ReferrerKiller.imageHtml("fakeweb/fakeimage.png"); 返回能夠顯示的 img 的 Html 字符串
ReferrerKiller.imageHtml("fakeweb/fakeimage.png"); 返回能夠顯示的 img 的 DOM 節(jié)點(diǎn)
其實(shí)這兩個(gè)函數(shù)是同一個(gè)東西,可以撿方便的用。
這種方式解決HotLinking 問(wèn)題其實(shí)原理很簡(jiǎn)單,在web中 比如:
<script src="differentDomain/fake.js"> </script>
script 標(biāo)簽是沒(méi)有跨域訪問(wèn)的問(wèn)題。
ReferrerKiller 就動(dòng)態(tài)生成一個(gè)iframe,并在iframe 內(nèi)加入img 標(biāo)簽。利用src 加載的特性把代碼放到src 中,就可以去掉Referer,所以:
ReferrerKiller.imageHtml
返回的是一個(gè)能顯示圖片的iframe
- 利用
html中的meta標(biāo)簽關(guān)閉瀏覽器的UrlReferer
<meta name="referrer" content="no-referrer" />
此方法簡(jiǎn)單粗暴!
部分內(nèi)容摘自: 關(guān)于img 403 forbidden的一些思考