Iris框架需通过自定义中间件+ctx.Request().Referer()实现Referer防盗链,关键是在静态资源路径(如/assets/)前精确挂载中间件、校验白名单(含同源与空Referer容错)、避免误拦截API,并注意Referer易伪造、非身份凭证的本质。

Iris 框架本身不内置 Referer 防盗链逻辑,但能通过 ctx.Request().Referer() + 中间件轻松实现,关键在判断时机、白名单匹配方式和静态资源路径的拦截范围。
如何用中间件拦截静态资源请求并校验 Referer
Iris 的静态文件服务(如 app.StaticWeb() 或 app.StaticFS())默认不经过常规路由中间件,必须显式用 app.UseRouter() 或在注册静态服务前挂载中间件,并确保中间件作用于对应路径前缀。
- 错误做法:在
app.Get("/assets/*file", handler)之后再挂载 Referer 中间件 —— 静态文件请求根本不会进这个路由 - 正确做法:用
app.UseRouter()注册一个作用于/assets/路径的中间件,在其中调用ctx.Next()继续后续处理(包括静态文件服务) - Referer 判定应忽略空值(直接地址栏访问)、同源(
ctx.Request().URL.Scheme + "://" + ctx.Request().Host)、以及明确配置的白名单域名 - 注意:Chrome 等浏览器在跨协议(如 HTTPS 页面引用 HTTP 资源)或设置了
Referrer-Policy: no-referrer-when-downgrade时可能不带 Referer,需预留 fallback 逻辑
ctx.Request().Referer() 返回值的常见陷阱
该方法返回的是请求头中 Referer 字段原始字符串,不是解析后的 URL 结构体,直接用 url.Parse() 可能 panic,且易被伪造。
- 空 Referer 不等于非法:用户从书签、HTTPS→HTTP 跳转、某些隐私模式下 Referer 为空,应允许通过或走备用验证(如 token 签名)
- 不能只比对域名:攻击者可构造
https://evil.com/xxx?referer=https%3A%2F%2Fyoursite.com并在页面里伪造 header,必须用net/url.URL.Host提取真实来源 host - 大小写敏感:
"https://EXAMPLE.COM"和"https://example.com"是不同 host,建议统一转小写再比对 - 端口影响匹配:本地开发常用
localhost:3000,生产是example.com,白名单列表需覆盖所有合法入口
静态资源路径与防盗链中间件的绑定方式
必须让中间件在静态文件处理器之前执行,且路径前缀要严格一致。Iris 不支持像 Gin 那样用 Use("/public", middleware) 精确绑定子路径中间件,得靠手动路径匹配。
- 推荐注册方式:
app.UseRouter(func(ctx iris.Context) { if strings.HasPrefix(ctx.Request().URL.Path, "/assets/") { referer := ctx.Request().Referer() if !isValidReferer(referer) { ctx.StatusCode(403) ctx.WriteString("Forbidden: invalid referer") return } } ctx.Next() }) - 然后调用
app.StaticWeb("/assets", "./public/assets")—— 注意路径前缀/assets必须和中间件里strings.HasPrefix(..., "/assets/")完全一致 - 避免用
app.StaticFS()时漏掉目录索引(如/assets/css/),这种请求的Path是/assets/css/,仍会被中间件捕获 - 若同时提供 API 接口(如
/api/),不要把 Referer 校验中间件挂到全局app.Use(),否则会误杀 AJAX 请求
白名单域名配置与性能考虑
硬编码白名单数组查起来快,但改配置要重启;用 map 查 O(1),但初始化需预处理 host 规范化。
- 建议初始化时构建
map[string]struct{},键为小写 host(不含 port 和 scheme),例如"example.com"、"admin.example.com" - 若需支持通配符(如
*.example.com),别手写正则——用net.SplitHostPort()提取 host 后,用strings.HasSuffix(host, ".example.com")更安全高效 - 静态资源通常高并发,避免在中间件里做 I/O(如读配置文件)或复杂计算;白名单应加载到内存常量或全局变量
- 测试时用 curl 手动构造 Referer 最可靠:
curl -H "Referer: https://evil.com" http://localhost:8080/assets/logo.png
真正容易被忽略的是 Referer 的语义边界:它只表示「上一页 URL」,不是身份凭证。一旦需要强校验(比如 CDN 回源鉴权),就得换方案——加签名参数、用 JWT token 或配合 Nginx 的 valid_referers 做前置过滤。Iris 中间件只适合轻量级业务防盗链。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











