搜索

📄 文章 📚 合集
热门搜索
🐘 PHP ⚡ Laravel 🎨 Vue.js ⚛️ React 📦 Yii 📘 JavaScript 🗄️ MySQL 🐳 Docker
返回首页

OSS防盗链实战:JS内部CSS加载失败的最简解决方案

代码示例
# OSS防盗链实战:JS内部CSS加载失败的最简解决方案

## 一、问题现象

我的网站使用了阿里云OSS存放静态资源(CSS、JS、图片等),并且开启了OSS防盗链,白名单里只加了自己的网站域名(比如 `88njhc.com`),**没有加OSS域名**。

结果出现了一个奇怪的现象:

- HTML里直接引入的CSS、JS → 能正常加载 ✅
- JS文件内部去加载的CSS → 加载失败 ❌

打开浏览器控制台,看到这些CSS文件返回403错误。但OSS白名单里明明已经有我的网站域名了,为什么JS内部加载的CSS就不行?

## 二、问题原因

OSS防盗链的判断规则是:**只看每个HTTP请求的Referer(来源)**。

- 当HTML直接加载CSS时,请求的Referer是 `https://myurl.com` → 白名单里有,放行 ✅
- 当JS内部动态加载CSS时,在某些浏览器或设备上,这个CSS请求的Referer会变成CSS文件所在的域名(也就是 `customer-project.oss-cn-shanghai.aliyuncs.com`),而不是我的网站域名

因为OSS白名单里没有加OSS自己的域名,所以这个请求被拒绝了 ❌

**矛盾点:** 如果在白名单里加上OSS域名,JS内部的CSS确实能加载,但OSS域名就暴露了,容易被别人盗刷流量,一天损失几百G。不加,JS内部的CSS又加载失败。

## 三、我的解决方案

**核心思路:** 不让JS去动态加载CSS,而是把JS需要的那几个CSS提前在HTML里用 `<link>` 直接引入。

### 具体做法

1. 找到是哪个JS文件在加载CSS(通过浏览器开发者工具的Network面板,看CSS请求的Initiator是谁)
2. 把这个JS文件里加载的那些CSS地址记录下来
3. 在网页模板的 `<head>` 标签里,直接用 `<link>` 标签把这些CSS提前引入

```html
<!-- 原本需要JS动态加载的CSS,直接写死在HTML里 -->
<link rel="stylesheet" href="https://myurl.com/static/css/animate.min.css">
<link rel="stylesheet" href="https://myurl.com/static/css/owl.carousel.css">
<!-- 其他CSS同理 -->
```

### 为什么这样就解决了?

- 这些CSS现在是由HTML直接加载的,而不是由JS动态加载的
- 它们的Referer是 `https://88njhc.com`,已经在OSS白名单里了
- 不需要把OSS域名加入白名单
- 不影响OSS防盗链的效果,别人仍然无法盗刷我的OSS流量

## 四、为什么没选Nginx反向代理方案?

网上很多教程推荐用Nginx反向代理来解决这个问题,我也试过。

配置Nginx把所有 `/static/` 请求代理到OSS,确实能让JS内部的CSS加载正常,但问题是我网站的**后台也用 `/static/` 路径存放静态资源**。代理规则一开,后台的所有CSS/JS也跑到OSS上去找了,而OSS上根本没有后台的这些文件,结果后台页面直接打不开,样式全乱。

这个方案影响范围太大,等于改了整个站点的资源加载规则,不适合我的环境。

## 五、方案的优缺点

### 优点
- 改动极小,只改前台HTML模板,不影响后台
- 不需要动Nginx、不需要改OSS配置、不需要动JS文件
- OSS白名单继续保持只有网站域名,防盗链依然有效
- 流量不会被盗刷
- 实施简单,几分钟就能搞定

### 缺点
- 需要手动找出每个JS里加载的CSS(不过一般一个站点也就两三个JS会有这种情况)
- 如果以后JS文件更新,引入了新的CSS,需要同步更新HTML

## 六、总结

**一句话:JS内部加载的CSS会因Referer问题被OSS防盗链拦截。把CSS提前在HTML里直接引入,就能绕开这个问题。**

不需要Nginx代理,不需要改OSS白名单,不需要动JS文件。最少的改动,解决最核心的问题。
none
none

🧸 adorable code

专注 PHP、JavaScript、Laravel、Vue.js、React、Yii 全栈开发。记录技术探索过程中的灵感与经验,分享工程实践洞见。

hello@adorablecode.com