一、前端安全到底在防什么?
核心目标只有一个:
防止用户可控的数据,被当成“代码”执行
攻击本质通常是:
- 注入(Injection)
- 越权(Auth / 权限)
- 信息泄露
- 供应链攻击
二、必考 & 必会的前端安全问题
1️⃣ XSS(跨站脚本攻击)⭐⭐⭐⭐⭐
本质
用户输入 → 被浏览器当 JS 执行
类型
| 类型 | 说明 |
|---|---|
| 存储型 | 恶意脚本存数据库 |
| 反射型 | URL 参数直接执行 |
| DOM 型 | JS 操作 DOM 导致 |
示例
html
<div id="app"></div>
<script>
const name = location.search.slice(6)
document.getElementById('app').innerHTML = name
</script>访问:
?name=<img src=x onerror=alert(1)>防御方案(重点)
✅ 永远不要信任用户输入
1️⃣ 输出编码(最重要)
js
element.textContent = userInput2️⃣ 避免 innerHTML / v-html / dangerouslySetInnerHTML
3️⃣ 富文本 → 白名单过滤
- DOMPurify
- sanitize-html
4️⃣ CSP(内容安全策略)
http
Content-Security-Policy:
default-src 'self';
script-src 'self';5️⃣ Cookie 设置
http
Set-Cookie: token=xxx; HttpOnly; Secure2️⃣ CSRF(跨站请求伪造)⭐⭐⭐⭐⭐
本质
利用浏览器自动携带 Cookie
示例
html
<img src="https://bank.com/transfer?to=hacker&money=10000">防御方案
1️⃣ CSRF Token(主流)
js
headers: {
'X-CSRF-TOKEN': token
}2️⃣ SameSite Cookie
http
Set-Cookie: session=xxx; SameSite=Lax3️⃣ 验证 Referer / Origin
3️⃣ 点击劫持(Clickjacking)
本质
iframe 透明覆盖,诱导点击
防御
http
X-Frame-Options: DENY或
http
Content-Security-Policy: frame-ancestors 'none';4️⃣ 前端鉴权 & 越权问题 ⭐⭐⭐⭐
常见错误
js
if (user.role === 'admin') {
showAdminButton()
}⚠️ 前端判断 ≠ 安全
正确原则
- 前端:展示控制
- 后端:权限校验
5️⃣ Token / JWT 安全 ⭐⭐⭐⭐
常见风险
- 存 localStorage → 易 XSS 窃取
- JWT 永不过期
推荐方案
| 场景 | 建议 |
|---|---|
| 登录态 | HttpOnly Cookie |
| Access Token | 短期 |
| Refresh Token | HttpOnly |
6️⃣ 前端加密能防什么?⭐⭐⭐
❌ 防不了:
- 调试
- 抓包
- 逆向
✅ 能防:
- 明文泄露
- 中间人(配合 HTTPS)
常见:
- HTTPS
- AES / RSA(只是混淆级别)
7️⃣ 供应链安全(现代前端新重点)⭐⭐⭐⭐
风险
- npm 包被投毒
- 依赖版本漂移
防御
package-lock.json / pnpm-lock.yamlnpm audit- 固定版本
- 私有 npm 仓库
三、框架层安全(Vue / React)
Vue
- 默认
自动转义 v-html= 高危- 指令参数注入(
:href="userInput")
React
- JSX 默认安全
dangerouslySetInnerHTML= 高危- 事件绑定安全(不会执行字符串)
四、真实项目中的安全 Checklist ✅
- ✔ 不使用
eval / new Function - ✔ API 全部走 HTTPS
- ✔ Token 不放 localStorage(或严格防 XSS)
- ✔ 重要操作二次确认
- ✔ 所有接口后端做鉴权
- ✔ 富文本必做 sanitize
- ✔ CSP + HttpOnly Cookie
五、面试高频问法(你一定会遇到)
- ❓ XSS 和 CSRF 有什么区别?
标准答案模板:
XSS 是向页面注入恶意脚本,攻击的是用户;
CSRF 是利用用户登录态发起非法请求,攻击的是服务器。
❓ 为什么前端不能做安全校验?
一句话:
- 前端代码是完全可被篡改的,只能作为体验优化,不能作为安全边界。