在服务器中实现图片防盗链,通常是通过检查HTTP请求头中的Referer字段来判断是否允许访问图片资源。如果请求来源不在白名单内,可以返回403错误或占位图片来拒绝访问。
Koa示例
const path = require('path')
const fs = require('fs')
const Koa = require('koa')
const PLACEHOLDER_IMG_NAME = 'placeholder.jpg'
const IMAGE_EXT_NAME_LIST = ['.jpg', '.png']
const DOMAIN_WHITELIST = ['localhost', '127.0.0.1']
const app = new Koa()
app.use(async (ctx, next) => {
if (IMAGE_EXT_NAME_LIST.includes(path.extname(ctx.path))) {
const referer = ctx.request.header?.referer;
if (!referer || !DOMAIN_WHITELIST.some((domain) => referer.includes(domain))) {
ctx.type = 'image/jpg'
ctx.body = fs.createReadStream(path.join(__dirname, `public/${PLACEHOLDER_IMG_NAME}`));
return console.error(`Request Referer Header: ${referer}`)
}
}
return next()
})
app.use(require('koa-static')(path.join(__dirname, 'public'), {
maxAge: 86400 * 1000, // 设置浏览器缓存时间,避免重复检查
gzip: true,
}))
app.listen(8080, () => console.info('服务运行在 http://localhost:8080 '))
使用HTML的iframe框架标签测试,如下图所示:
从白名单中移除127.0.0.1,刷新页面(由于设置了图片缓存,需要清除浏览器缓存),此时会返回占位图片,如下图所示:
是否允许没有Referer的请求?
虽然禁止无Referer的请求可以增加保护力度,但是会使某些合法请求被拒绝(例如,用户直接在浏览器地址栏输入图片地址)。因此,需要根据实际情况调整防盗策略。
注意
- Referer不可靠
- 因为Referer是由客户端发送,所以可能会被伪造
- 可以结合
token验证实现更高级别的保护
- 影响性能
- 防盗链中间件可能会影响图片请求的性能,尤其是在高并发环境下
- 使用
CDN配合服务器完成防盗链策略