---
title: "8.5 进阶安全防护"
description: "SQL 注入、XSS、CSRF 防护,AI 应用安全,依赖审计——了解更深层的安全威胁"
chapter: "第八章"
---
# 8.5 进阶安全防护
> **本节目标**:了解常见的 Web 安全攻击原理和防护方式,以及 AI 应用特有的安全问题。
---
## 基础安全之上
前面几节解决了最紧迫的问题:密钥不泄露、用户能认证、路由有保护。这些是"入门必修课"。但当你的应用有了真实用户,就会面临更复杂的安全威胁。好消息是,如果你用的是 Next.js + Drizzle + React 这套技术栈,**大部分防护已经内置了**。本节帮你理解这些威胁是什么——不是为了吓你,而是让你在遇到相关报错或安全告警时知道怎么回事。
## SQL 注入——让数据库执行恶意代码
小明给"个人豆瓣"加了搜索功能——用户输入电影名,后端去数据库里查。功能上线后,有个朋友在搜索框里输了一串奇怪的东西:`' OR 1=1 --`。结果页面显示了**所有电影**,包括小明标记为"私密"的几部。朋友截图发到群里:"你的搜索功能有 bug,我搜了个奇怪的东西,所有电影都出来了。"
这不是 bug,这是 **SQL 注入攻击**。假设搜索功能直接把用户输入拼接到 SQL 里:`SELECT * FROM movies WHERE title = '用户输入的内容'`。正常情况下,用户输入"流浪地球",拼接后是 `SELECT * FROM movies WHERE title = '流浪地球'`,没问题。但如果用户输入的不是电影名,而是 `'; DROP TABLE movies; --`,拼接后变成 `SELECT * FROM movies WHERE title = ''; DROP TABLE movies; --'`。分号把一条 SQL 变成了两条,第二条是删表命令,`--` 把后面的内容注释掉了。数据库会先查询,然后**删掉整张表**。攻击者通过精心构造的输入,让数据库执行他想要的操作——这就是"注入"的含义:把恶意代码"注入"到了你的 SQL 语句里。
**用 ORM 就不用担心。** Drizzle、Prisma 这些 ORM 会自动对用户输入做参数化处理——用户输入的内容永远被当作"数据",不会被当作"SQL 命令"执行。不管用户输入什么奇怪的字符串,ORM 都会把它安全地包裹起来,数据库只会把它当作一个普通的搜索关键词。
```typescript
// Drizzle 自动防护 SQL 注入
const results = await db.select().from(movies)
.where(eq(movies.title, userInput)) // userInput 被安全处理
```
唯一需要注意的是:**不要手写原始 SQL 拼接用户输入**。如果你确实需要写原始 SQL,用参数化查询:
```typescript
// ✅ 安全:参数化查询
await db.execute(sql`SELECT * FROM movies WHERE title = ${userInput}`)
// ❌ 危险:字符串拼接
await db.execute(`SELECT * FROM movies WHERE title = '${userInput}'`)
```
## XSS——在别人的页面上执行恶意脚本
小明给电影加了评论功能。某天他发现一条奇怪的评论——内容看起来是空的,但打开浏览器开发者工具一看,评论的 HTML 里藏着一段 JavaScript 代码。更可怕的是,其他用户打开这个电影的页面时,这段代码会悄悄执行,把他们的登录 Cookie 发送到一个陌生的服务器。攻击者拿到 Cookie 后,就能冒充这些用户登录。
这就是 **XSS(跨站脚本攻击)**——攻击者把恶意代码注入到你的网页中,让其他用户的浏览器执行。和 SQL 注入类似,XSS 的本质也是"用户输入被当作代码执行了"——只不过 SQL 注入是在数据库端,XSS 是在浏览器端。比如攻击者提交这样的"评论":``,如果直接把用户输入渲染到页面上,浏览器会把这段内容当作 HTML 解析,发现里面有 `