--- 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 解析,发现里面有 `