关于img 403 forbidden的一些思考

网页中常常须要显示图片给用户看,对网站自己来讲有的图片是从本地图片服务器来的,可是一旦数量多了之后,磁盘空间又是一个问题。git

因此有时就但愿显示其余网站的Image,直接把其余网站的图片显示在个人网站上。但并非全部的外网Image 都能直接链接过来显示。web

不少状况下网站开发人员就会遇到 403 forbidden的问题。好比想显示来自IMDB的一张图片chrome

<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等加密协议google

这就是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。

 

欢迎访问个人我的主页 51zhang.net  网站还在不断开发中…..

相关文章
相关标签/搜索