Node服务实现图片防盗链

234 阅读1分钟

在服务器中实现图片防盗链,通常是通过检查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 '))

使用HTMLiframe框架标签测试,如下图所示:

Screenshot 2025-01-09 at 00.55.30.png

从白名单中移除127.0.0.1,刷新页面(由于设置了图片缓存,需要清除浏览器缓存),此时会返回占位图片,如下图所示:

Screenshot 2025-01-09 at 01.03.37.png

是否允许没有Referer的请求?

虽然禁止无Referer的请求可以增加保护力度,但是会使某些合法请求被拒绝(例如,用户直接在浏览器地址栏输入图片地址)。因此,需要根据实际情况调整防盗策略。

注意

  1. Referer不可靠
    • 因为Referer是由客户端发送,所以可能会被伪造
    • 可以结合token验证实现更高级别的保护
  2. 影响性能
    • 防盗链中间件可能会影响图片请求的性能,尤其是在高并发环境下
    • 使用CDN配合服务器完成防盗链策略