防盗链问题
防盗链问题
配置OSS Bucket的Referer黑白名单可以防止资源被非法盗用,从而降低不必要的流量成本。
防盗链的核心作用是保护你存储资源的权益与成本,避免第三方未经授权滥用你的资源,结合你使用阿里云 OSS+VuePress 博客的场景,具体作用可分为以下几点:
- 降低不必要的带宽成本
你的阿里云 OSS 资源(如博客图片)若被其他网站直接嵌入引用(即 “盗链”),这些网站的用户访问图片产生的流量会算在你的 OSS 带宽账单中 —— 防盗链通过限制仅授权域名(如你的liqing6666666.github.io博客、OSS 控制台)可访问资源,阻断第三方盗链的流量消耗,减少你的存储费用支出。
- 保护资源的版权与归属
你博客中的图片、笔记素材是自己整理 / 创作的内容,防盗链能避免这些资源被其他网站无授权引用、甚至篡改来源(比如直接复制你博客的图片用于他人内容),维护你对资源的版权与归属权。
- 规避合规与安全风险
若你的资源被不良网站(如侵权、违规内容的站点)盗链,可能因 “资源关联违规内容” 产生合规风险;同时,盗链带来的大量异常请求也可能挤占你 OSS 的访问资源,导致自己博客的图片加载变慢、甚至访问拥堵 —— 防盗链可从访问源头拦截这类风险,保障自身业务的稳定性。
- 精准控制资源的访问范围
通过配置白名单(如你添加的*.github.io、*.aliyun.com),防盗链能实现 “仅你授权的场景可访问资源”:既保证自己的博客、OSS 控制台能正常加载图片,又阻止其他无关站点 / 用户滥用你的资源。
配置防盗链

配置防盗链后,OSS将按照以下优先级顺序执行访问控制判断:
- 空Referer检查
- OSS首先判断请求的Referer字段是否为空。
- 如果为空:
- 如果配置了允许空Referer,请求将通过。
- 如果配置了不允许空Referer,则会进入一个特殊判断:只有当白名单也为空时,请求才会被允许;否则,请求将被拒绝。
- 黑名单检查
- 对于Referer不为空的请求,OSS会检查黑名单。
- 如果请求的Referer匹配到黑名单中的任何一项,请求将立即被拒绝,后续的白名单检查不再进行。
- 白名单检查
- 如果请求的Referer不为空,且没有命中黑名单,OSS会最后检查白名单。
- 如果请求的Referer能匹配到白名单中的某一项,请求将通过。
- 如果遍历完整个白名单都无法匹配,请求将被拒绝。
因为主要是配置白名单,这个阿里云官网的意思就是,你必须要使用允许空Referer,所以你的图片的格式就必须加上 referrerPolicy="no-referrer"
<-- referrerPolicy="no-referrer" !-->
<-- 比如这个 !-->
<img src="https://liqing666.oss-cn-wuhan-lr.aliyuncs.com/image_typora/20251222174842274.png" alt="image-20251222174842148" style="zoom:50%;" referrerPolicy="no-referrer" />可以先看完再操作,因为后面两种方法不太行
或者(不行)
<meta name="referrer" content="never">或者(不行)
<!-- 修改HTML头部,添加referrerPolicy -->
<head>
<base referrerPolicy="no-referrer" />
</head>我用的是博客就直接在配置文件里面添加了


然后去问了一下AI,然后尝试了一个小时
- 环境确认:VuePress 2.x 版本(已安装
@vuepress/client依赖,版本与@vuepress/core一致,如 2.0.0-rc.26); - 文件路径:确保项目目录结构中存在
src/.vuepress/文件夹(用于存放配置文件); - OSS 配置:阿里云 OSS 防盗链中已勾选「允许空 Referer」(避免无 Referer 的图片请求被拦截)。
在 src/.vuepress/ 目录下创建 client.ts(与 config.ts 同级),作为 VuePress 客户端配置入口,初始写入基础结构:
// src/.vuepress/client.ts
import { defineClientConfig } from "@vuepress/client";
import { nextTick } from "vue";
export default defineClientConfig({
setup() {
// 核心函数:给img添加referrerPolicy
const addReferrerPolicy = () => {
const imgs = document.querySelectorAll("img");
console.log(`当前找到img标签数量:${imgs.length}`);
imgs.forEach((img) => {
if (!img.hasAttribute("referrerPolicy")) {
img.setAttribute("referrerPolicy", "no-referrer");
console.log("已给1张img添加属性");
}
});
};
// 方案1:Vue nextTick + 多级延迟,确保等待页面内容渲染
const initImgPolicy = async () => {
// 第一步:等待Vue组件首次渲染完成
await nextTick();
addReferrerPolicy();
// 第二步:轻微延迟(应对异步渲染的内容)
setTimeout(() => {
addReferrerPolicy();
}, 100);
// 第三步:稍长延迟(应对懒加载/慢渲染的图片)
setTimeout(() => {
addReferrerPolicy();
}, 500);
};
// 立即执行初始化
initImgPolicy();
// 方案2:监听路由切换(页面跳转后重新初始化)
window.addEventListener("routeChangeAfter", async () => {
await nextTick();
setTimeout(addReferrerPolicy, 100);
});
// 方案3:监听DOM动态变化(捕获后续新增的img标签,如懒加载图片)
const domObserver = new MutationObserver((mutations) => {
// 只要有新节点添加,就重新执行属性添加
let hasNewNode = false;
mutations.forEach((mutation) => {
if (mutation.addedNodes.length > 0) {
hasNewNode = true;
}
});
if (hasNewNode) {
addReferrerPolicy();
}
});
// 监听整个文档的body区域(包括所有后代节点变化)
domObserver.observe(document.body, {
childList: true, // 监听子节点添加/删除
subtree: true, // 监听所有后代节点
attributes: false,
characterData: false,
});
},
});可以看到各个部分都已经添加了Referer
