介绍
作为网站开发者,我们有时候不希望自己网站地上的图片被其他网站直接引用。这在某些场景下会导致自己数据中心里巨大的带宽消耗,也就意味着别人使用我们的图片,而我们要为此付钱。例如,你的网站是a.com,你有一张图片是http://a.com/facepalm.jpg,而b.com在他们的网站上使用一个img标签来引用了你的图片,这导致网络请求是进入你的数据中心,消耗你的资源。
许多网站可以屏蔽图片盗链。我这就来教大家如何在ASP.NET或ASP.NET Core应用里实现防盗链。
我所采用的技术是URL重写。我们都知道,每一个HTTP请求都有一些header,其中有一个是“HTTP referer”,你可以在维基百科找到详细介绍(https://en.wikipedia.org/wiki/HTTP_referer)。这同样作用于对图片文件的请求,如果一个图片是被另一个网站所引用的,那么这个请求的header中将包含值为另一个网站域名的HTTP Referer。
在上述的例子里,如果用户访问了b.com的网页看到了http://a.com/facepalm.jpg的图片,对于a.com的网站服务器来说,这个图片请求的http header的referer值将是http://b.com....开头的。这就是我们要检查并阻止的请求。
ASP.NET (.NET Framework) 应用
对于运行在IIS上的传统ASP.NET (.NET Framework)应用,你需要额外安装一个URL Rewrite拓展:https://www.iis.net/downloads/microsoft/url-rewrite
在网站根目录下创建一个UrlRewrite.config文件,内容如下:
<rules>
<rule name="Prevent Image Hotlinking">
<match url=".*\.(gif|jpg|png)$"/>
<conditions>
<add input="{HTTP_REFERER}" pattern="^$" negate="true"/>
<add input="{HTTP_REFERER}" pattern="^http://a.com/.*$" negate="true"/>
</conditions>
<action type="Rewrite" url="/content/images/no_hotlinking.png"/>
</rule>
</rules>
这条规则的含义是,遇到.gif, .jpg, .png的图片文件,检查HTTP Referer的header,如果不是以http://a.com开头的,返回事先准备好的图片/content/images/no_hotlinking.png,也就是这个:
接下来,在web.config的system.webServer节点下加入以下片段
<rewrite>
<rules configSource="UrlRewrite.config" />
</rewrite>
ASP.NET Core 应用
对于ASP.NET Core应用来说,你不需要在托管环境上安装任何额外的东西。
在你的网站根目录下准备一个类似文件UrlRewrite.xml,但有一处不同:你需要将rewrite节点定义为根节点。
<rewrite>
<rules>
<rule name="Prevent Image Hotlinking">
<match url=".*\.(gif|jpg|png)$"/>
<conditions>
<add input="{HTTP_REFERER}" pattern="^$" negate="true"/>
<add input="{HTTP_REFERER}" pattern="^http://a.com/.*$" negate="true"/>
</conditions>
<action type="Rewrite" url="/images/no_hotlinking.png"/>
</rule>
</rules>
</rewrite>
注意:你需要将这个文件设置为拷贝到输出目录,不然不起作用
<ItemGroup>
<None Update="UrlRewrite.xml"><CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
打开Startup.cs,将这段代码添加到Configure方法中
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
using (var urlRewriteStreamReader = File.OpenText("UrlRewrite.xml"))
{
var options = new RewriteOptions().AddIISUrlRewrite(urlRewriteStreamReader);
app.UseRewriter(options);
}
...
}
现在,它和上面的ASP.NET Framework的网站一样可以顺利防盗链了!
Tips
一些技巧
在真实场景里,网站通常有多个域名以及HTTP/HTTPS多个绑定,甚至还有不同的端口号,就像这样:
生产环境
开发环境
你不需要逐个手动添加,我们可以利用正则表达式:)
例如,我博客网站的防盗链规则如下:
<add input="{HTTP_REFERER}" pattern="^$" negate="true"/>
<add input="{HTTP_REFERER}" pattern="^https?:\/\/.*edi.wang:?\d{0,5}?\/.*$" negate="true"/>
<add input="{HTTP_REFERER}" pattern="^https?:\/\/localhost:?\d{0,5}?\/.*$" negate="true"/>
<add input="{HTTP_REFERER}" pattern="^https?:\/\/.*azurewebsites.net:?\d{0,5}?\/.*$" negate="true"/>