测试环境显示 1688 图片:referrerpolicy: 'no-referrer' 实践说明
背景
业务页面经常需要展示来自阿里巴巴 / 1688 CDN 的商品图,典型域名包括:
cbu01.alicdn.comglobal-img-cdn.1688.com
在线上(正式域名)访问时,这些图片通常可以正常加载。但在测试环境 (本地 localhost、内网测试域名、非白名单域名)里,同 URL 的图片经常会出现:
- 裂图 / 空白
- 控制台报
403/ 防盗链相关错误 - Network 面板里请求被 CDN 拒绝
表面看像是「图片地址错了」,实际多数是 Referer 防盗链 拦截。
原因:CDN 会校验 Referer
浏览器请求外链图片时,默认会带上当前页面的 Referer(来源页地址)。例如:
| 当前页面 | 请求图片时带上的 Referer(示意) |
|---|---|
https://product.xxx.com/... |
https://product.xxx.com/ |
http://localhost:3000/... |
http://localhost:3000/ |
https://test-xxx.company.com/... |
https://test-xxx.company.com/ |
1688 / 阿里 CDN 会对 Referer 做白名单校验:
- 正式业务域名:通常在白名单内 → 图片可访问
- 测试 / 本地域名:不在白名单 → CDN 拒绝返回图片
所以:同一张 1688 图片 URL,在正式环境能看、在测试环境不能看,往往不是业务代码拼错路径,而是 Referer 策略差异。
解决方案:不发送 Referer
HTML 图片标签支持 referrerpolicy。设置为 no-referrer 后,浏览器在请求该图片时不携带 Referer。
对许多 CDN 而言:
- 有非法 / 非白名单 Referer → 拒绝
- 没有 Referer → 允许放行(或按宽松策略处理)
因此测试环境可通过「不传 Referer」绕过防盗链限制,从而正常显示 1688 图片。
说明:这是前端展示层的兼容手段,不改变图片 URL 本身,也不替代后端镜像 / 代理方案。
在 Naive UI n-image 中的用法
项目里使用 Naive UI 的 n-image。底层最终会渲染原生 <img>,可通过 :img-props 把属性透传给真实 img 节点。
示例(寻源关联抽屉 sourceModel.vue):
vue
<n-image
class="w-[70px] h-[70px] rounded-md"
:img-props="{ referrerpolicy: 'no-referrer' }"
:src="item?.includes('//cbu01.alicdn.com/') ? item : getPathImage(item, 120, 120)"
:preview-src="item?.includes('//cbu01.alicdn.com/') ? item : getPathImage(item, 0, 0)"
/>
关键点:
ts
:img-props="{ referrerpolicy: 'no-referrer' }"
n-image 的 :img-props 最终会落到原生 <img> 上,效果与下一节的原生写法一致。
原生 <img> 中的用法
不依赖组件库时,直接在 <img> 上写 referrerpolicy="no-referrer" 即可。
HTML
html
<img
src="https://cbu01.alicdn.com/img/ibank/xxx.jpg"
alt="1688商品图"
referrerpolicy="no-referrer"
width="120"
height="120"
/>
Vue 模板
vue
<img
class="w-[70px] h-[70px] rounded-md"
referrerpolicy="no-referrer"
:src="item?.includes('//cbu01.alicdn.com/') ? item : getPathImage(item, 120, 120)"
alt="商品图"
/>
属性也可以写成绑定形式(效果相同):
vue
<img
:referrerpolicy="'no-referrer'"
:src="aliImageUrl"
alt="商品图"
/>
动态创建 Image 对象
用 JS 预加载、导出画布、或自定义预览时,记得给 DOM/Image 实例设置 referrerPolicy(注意驼峰):
js
const img = new Image()
img.referrerPolicy = 'no-referrer'
img.onload = () => {
// 加载成功后再绘制 / 展示
}
img.src = 'https://cbu01.alicdn.com/img/ibank/xxx.jpg'
Vue 里通过 ref 操作原生节点时同理:
ts
imgRef.value.referrerPolicy = 'no-referrer'
imgRef.value.src = aliUrl
n-image 与原生 <img> 对照
| 写法 | 如何设置 |
|---|---|
Naive UI n-image |
:img-props="{ referrerpolicy: 'no-referrer' }" |
原生 <img> |
referrerpolicy="no-referrer" |
new Image() |
img.referrerPolicy = 'no-referrer'(驼峰) |
三者原理相同:让图片请求不携带 Referer,从而在测试环境通过 1688 CDN 防盗链校验。
和现有图片处理逻辑的配合
项目中站内图一般走 getPathImage 做裁剪 / WebP;1688 CDN 图通常原样使用,不走站内缩略图规则:
ts
item?.includes('//cbu01.alicdn.com/')
? item
: getPathImage(item, 120, 120)
建议约定:
- 1688 / 阿里 CDN 外链 :直接用原 URL +
referrerpolicy: 'no-referrer' - 站内 OSS / 自有 CDN :继续走
getPathImage src与preview-src保持同一套判断,避免缩略图与预览图策略不一致
如何验证
- 打开测试环境含 1688 图片的页面。
- DevTools → Network → 筛选图片请求。
- 查看 Request Headers:
- 修复前 :通常带有
Referer: http://localhost:...或测试域名 - 修复后 :该图片请求没有
Referer(或策略符合no-referrer)
- 修复前 :通常带有
- 图片应可正常显示;若仍失败,再排查 URL 是否过期、是否需
https、是否被公司网络拦截。
也可在控制台快速对比:
js
// 可能失败(带当前页 Referer)
const img1 = new Image()
img1.src = 'https://cbu01.alicdn.com/xxx.jpg'
// 更可能成功(不带 Referer)
const img2 = new Image()
img2.referrerPolicy = 'no-referrer'
img2.src = 'https://cbu01.alicdn.com/xxx.jpg'
适用场景与注意点
适合
- 测试 / 本地调试需要看 1688 商品图
- 前端直接用
n-image/<img>展示外链 - 临时兼容防盗链,快速恢复联调体验
注意
-
不是万能钥匙
若 CDN 强制要求合法 Token、Cookie、签名 URL,仅去掉 Referer 仍可能失败。
-
预览层也要透传
n-image的预览大图若另起一层 DOM,确认预览用的img同样带上referrerpolicy(当前通过img-props一般可覆盖主图;若自定义预览组件,需单独处理)。 -
安全与合规
no-referrer会隐藏来源信息。仅用于展示外链资源时是常见做法;不要把它当成绕过业务鉴权的通用方案。 -
生产环境是否也要加
正式域名通常已在白名单,可不依赖该属性。但加上一般无副作用,可减少「测试能看、线上偶发裂图」的差异;团队可统一在展示 1688 图的组件上默认开启。
-
CSS / 背景图无效
referrerpolicy只作用于<img>(以及部分带该属性的请求)。background-image: url(...)不能 通过该属性控制 Referer,外链背景图仍可能被防盗链拦截,需改用<img>或服务端代理。
推荐落地方式
在需要展示 1688 图的列表 / 抽屉 / 详情中,统一加上 no-referrer:
使用 n-image:
vue
<n-image
:img-props="{ referrerpolicy: 'no-referrer' }"
:src="isAliCdn(url) ? url : getPathImage(url, 120, 120)"
:preview-src="isAliCdn(url) ? url : getPathImage(url, 0, 0)"
/>
使用原生 <img>:
vue
<img
referrerpolicy="no-referrer"
:src="isAliCdn(url) ? url : getPathImage(url, 120, 120)"
alt="商品图"
/>
可抽一个小工具函数:
ts
export const isAliCdn = (url = '') =>
url.includes('cbu01.alicdn.com') || url.includes('global-img-cdn.1688.com')
后续新页面复制同一模式,避免测试环境再次出现「1688 图全裂」的问题。
小结
| 项目 | 说明 |
|---|---|
| 现象 | 测试环境 1688 图片裂图,正式环境正常 |
| 根因 | CDN Referer 防盗链,测试域名不在白名单 |
手段(n-image) |
:img-props="{ referrerpolicy: 'no-referrer' }" |
手段(原生 img) |
referrerpolicy="no-referrer" |
| 效果 | 请求图片时不带 Referer,测试环境可正常显示 |
| 项目示例 | src/views/product/sourceModel.vue |
一句话:测试环境显示不了 1688 图时,优先给 n-image / <img> 加上 referrerpolicy: 'no-referrer'。