我的文档库

安全实践

从浏览器安全模型到 XSS、CSRF、CSP、Session 与供应链攻击,建立现代前端安全体系

前端安全最容易出现的误区是:

“前端代码都是公开的,所以没什么安全可做。”

实际上前端承担的是:

输入
展示
身份
请求
状态
第三方 SDK
浏览器能力

因此前端安全的核心不是:

隐藏 JavaScript。

而是:

正确理解浏览器的安全边界。


1. Origin 是浏览器安全模型的基础

一个 Origin:

scheme
+
host
+
port

例如:

https://example.com:443

与:

http://example.com:80

不是同一个 Origin。


2. Same-Origin Policy

浏览器不会允许一个 Origin 随意读取另一个 Origin 的资源。

例如:

https://evil.example

不能随意读取:

https://bank.example

中的页面数据。

这就是:

Same-Origin Policy

的重要意义。


3. CORS 是什么?

CORS 不是:

“关闭浏览器跨域。”

而是:

服务器通过 HTTP 响应头告诉浏览器,哪些跨 Origin 请求可以被 JavaScript 读取。

例如:

Access-Control-Allow-Origin: https://example.com

注意:

CORS 是浏览器安全机制。

服务器之间直接请求并不受浏览器 CORS 限制。


4. XSS

XSS 的核心:

Untrusted Input
       ↓
HTML / JS Context
       ↓
Browser Execution

常见来源:

  • innerHTML
  • dangerouslySetInnerHTML
  • URL
  • Markdown
  • 富文本
  • 第三方内容

例如:

element.innerHTML = userInput

如果:

userInput

未经正确处理,就可能产生 XSS。


5. 为什么 React 默认情况下相对安全?

React 通常会对:

<div>{value}</div>

进行转义。

所以:

<div>
  {userInput}
</div>

和:

<div
  dangerouslySetInnerHTML={{
    __html: userInput
  }}
/>

安全模型完全不同。

第二种相当于:

“我明确告诉框架,这段字符串就是 HTML。”

因此必须谨慎。


6. CSP

CSP:

Content Security Policy

可以理解成:

告诉浏览器哪些资源、脚本和行为是允许的。

例如:

Content-Security-Policy:
  default-src 'self';
  script-src 'self';

如果攻击者注入:

<script src="https://evil.example/x.js">

浏览器可以根据 CSP 阻止执行。

但:

CSP 不是 XSS 的替代品。

正确思路是:

输入验证
+
输出编码
+
安全框架
+
CSP

形成纵深防御。


7. Nonce CSP

现代严格 CSP 可以使用:

nonce

例如:

script-src 'nonce-abc123'

HTML:

<script nonce="abc123">

只有匹配 nonce 的脚本才允许执行。

关键点:

nonce 必须具有足够随机性,并且每次响应都应该重新生成。


8. CSRF

CSRF 的核心不是:

“黑客拿到了 Cookie。”

而是:

浏览器可能自动携带用户身份信息,使攻击者诱导用户浏览器向目标站点发起带认证信息的请求。

例如:

用户已经登录
      ↓
Cookie 自动存在
      ↓
恶意页面诱导请求
      ↓
目标服务器看到合法 Cookie

9. CSRF 防御

常见策略:

SameSite Cookie
+
CSRF Token
+
Origin / Referer 校验
+
服务端鉴权

特别需要注意:

CSRF 防护必须在服务端完成。

前端隐藏按钮:

不是安全边界。

推荐:

Set-Cookie:
  session=xxx;
  HttpOnly;
  Secure;
  SameSite=Lax;

其中:

HttpOnly

JavaScript 无法直接读取:

document.cookie

中的这个 Cookie。

因此可以降低部分 XSS 直接窃取 Session Cookie 的风险。


Secure

只通过:

HTTPS

发送。


SameSite

控制跨站请求中的 Cookie 发送行为。


11. LocalStorage 存 Token 有什么问题?

例如:

localStorage.setItem(
  'token',
  token
)

一旦发生 XSS:

localStorage.getItem('token')

可能直接读取。

因此对于高价值 Session,常见设计是:

HttpOnly Cookie

而不是:

localStorage Token

但最终方案仍然需要结合:

架构
跨域需求
CSRF 模型
API 设计

综合决定。


12. “前端鉴权”不是安全边界

例如:

if (user.role === 'admin') {
  showDeleteButton()
}

只能控制:

UI

不能控制:

Authorization

攻击者完全可以:

curl
Postman
自定义请求

直接调用 API。

因此:

Frontend Permission
        ↓
UX

Backend Authorization
        ↓
Security

二者必须分开。


13. 第三方 SDK 是巨大的攻击面

例如:

  • Analytics
  • Ads
  • Chat
  • A/B Test
  • Payment
  • Social Login

第三方 JavaScript 一旦被加载:

<script src="third-party.js">

它通常就在你的页面上下文中运行。

因此供应链安全需要关注:

  • 依赖数量
  • 依赖来源
  • 版本锁定
  • Subresource Integrity
  • CSP
  • 第三方脚本权限
  • 依赖漏洞扫描

14. 依赖供应链攻击

现代前端:

npm install

实际上引入了:

你的代码
 ↓
依赖
 ↓
依赖的依赖
 ↓
更多依赖

形成:

Dependency Graph

因此:

一个 npm package 被攻击,可能影响整个应用。

成熟工程需要:

Lockfile
+
Dependency Audit
+
版本策略
+
权限控制
+
构建隔离

15. 安全 Headers

常见安全 Header:

  • Content-Security-Policy
  • Strict-Transport-Security
  • X-Content-Type-Options
  • Referrer-Policy
  • Permissions-Policy

以及与页面嵌入相关的:

frame-ancestors

安全 Header 的意义不是:

“加几个 Header 就安全了。”

而是:

让浏览器参与执行安全策略。


16. 安全的真正模型

成熟 Web 应用应该形成:

Browser
   ↓
Origin Boundary
   ↓
HTTPS
   ↓
Cookie / Session
   ↓
Authentication
   ↓
Authorization
   ↓
Input Validation
   ↓
Output Encoding
   ↓
CSP
   ↓
Monitoring

每一层解决不同问题。

本页目录