API 接口作为现代应用的数据枢纽,一旦失守,轻则数据泄露,重则整个系统沦为攻击者的跳板。很多团队在开发 API 时,往往把精力集中在业务逻辑和性能上,安全防护却停留在“加个 token 就完事”的阶段。实际上,XSS 和注入攻击至今仍是 OWASP Top 10 中的常客,而它们的入口常常就是那些看似不起眼的 API 接口。本文从 XSS 的前端防御、MySQL 的 SQL 注入防范,以及 Linux 服务器加固三个层面,给出一份可落地的安全清单。
XSS 的常见方式与前端如何防御
XSS(跨站脚本攻击)的本质是攻击者将恶意脚本注入到网页中,当其他用户访问时脚本执行,从而窃取 Cookie、会话令牌或发起蠕虫式传播。在 API 场景下,XSS 往往通过接口返回的数据“回流”到前端页面触发。
常见 XSS 注入方式
- 反射型 XSS:恶意脚本作为请求参数发送到服务器,服务器未经处理直接返回在响应中。例如搜索接口
/api/search?q=<script>alert(1)</script>,如果前端直接把q渲染到页面,脚本就会执行。 - 存储型 XSS:攻击者将恶意内容提交到 API(如评论、昵称、地址),服务器存入数据库,其他用户读取该数据时脚本执行。这类 XSS 危害最大,因为不需要诱导用户点击特定链接。
- DOM 型 XSS:完全不经过服务器,前端 JavaScript 从 URL 或
localStorage中取出数据,直接通过innerHTML、document.write等方式插入 DOM,导致脚本执行。
前端防御的核心原则
第一,永远不要信任接口返回的数据。 即使数据来自自家后端,也可能因为存储型 XSS 已经被污染。渲染到页面前必须做转义或净化。
第二,优先使用安全的 API。 用 textContent 代替 innerHTML,用 setAttribute 代替直接拼接 HTML 字符串。React、Vue 等框架默认会对插值进行转义,但 dangerouslySetInnerHTML 和 v-html 会绕过这层保护,使用前必须用 DOMPurify 等库净化。
第三,设置 Content-Security-Policy(CSP)。 通过 HTTP 响应头限制脚本来源,例如 script-src 'self',可以大幅降低 XSS 成功执行的概率。CSP 是纵深防御的重要一环,但不能替代输入输出处理。
第四,对 Cookie 设置 HttpOnly 和 SameSite。 HttpOnly 让 JavaScript 无法读取 Cookie,SameSite 可以缓解 CSRF 和部分 XSS 场景下的会话窃取。
MySQL 防止 SQL 注入的几种写法
SQL 注入的根源是用户输入被当作 SQL 代码执行。在 API 开发中,任何拼接 SQL 字符串的行为都是高危的。以下是几种正确的防御写法,按推荐程度排序。
1. 参数化查询(预处理语句)——首选方案
参数化查询将 SQL 语句和参数分开传输,数据库先编译语句结构,再绑定参数值,参数永远不会被解释为 SQL 代码。
-- 以 Node.js mysql2 为例
const sql = 'SELECT * FROM users WHERE email = ? AND status = ?';
connection.execute(sql, [email, status]);
无论 email 传入什么内容,都只会被当作字符串值处理。这是防御 SQL 注入最有效的方式。
2. 使用 ORM 框架的查询构造器
主流 ORM(如 Sequelize、TypeORM、Hibernate、GORM)默认使用参数化查询,但要注意避免使用“原始查询”接口拼接字符串。
// 安全:ORM 自动参数化
User.findAll({ where: { email: req.body.email } });
// 危险:原始查询拼接
sequelize.query(`SELECT * FROM users WHERE email = '${req.body.email}'`);
3. 输入验证与白名单
对于排序字段、表名等无法用参数占位符的地方,必须使用白名单校验。
const allowedColumns = ['created_at', 'updated_at', 'name'];
if (!allowedColumns.includes(sortBy)) {
throw new Error('Invalid sort column');
}
const sql = `SELECT * FROM users ORDER BY ${sortBy} DESC`;
4. 最小权限原则
数据库账号只授予必要的权限。API 使用的账号不应有 DROP、FILE、GRANT 等权限,即使被注入,攻击者能造成的破坏也有限。
Linux 服务器安全加固清单
API 服务最终运行在 Linux 服务器上,系统层面的加固是最后一道防线。以下清单适用于大多数生产环境。
账户与认证
- 禁用 root 远程 SSH 登录,使用普通用户 +
sudo。 - 禁止密码登录,只允许 SSH 密钥认证。
- 修改 SSH 默认端口,减少自动化扫描。
- 使用
fail2ban自动封禁多次登录失败的 IP。
网络与防火墙
- 只开放必要端口(如 80、443、SSH 自定义端口),其余一律关闭。
- 使用
iptables或ufw设置默认拒绝策略。 - 数据库(MySQL、Redis)只监听
127.0.0.1,不暴露公网。 - API 服务与数据库分离部署,通过内网通信。
系统更新与监控
- 开启自动安全更新:
unattended-upgrades(Debian/Ubuntu)或yum-cron(CentOS)。 - 定期检查
lastb、/var/log/auth.log,发现异常登录尝试。 - 安装
auditd监控关键文件(如/etc/passwd、/etc/ssh/sshd_config)的变更。 - 使用
lynis做定期安全审计,生成加固建议。
服务与文件权限
- 以非 root 用户运行 API 服务,使用 systemd 的
User=和Group=指定。 - 敏感配置文件权限设为
600,属主为服务运行用户。 - 禁用不必要的服务(如
telnet、ftp、rpcbind)。 - 为
/tmp挂载noexec、nosuid选项,防止恶意脚本执行。
日志与备份
- 集中收集日志到远程服务器,避免攻击者入侵后清除本地日志。
- 定期备份数据库和关键配置,备份文件加密存储。
- 测试备份恢复流程,确保备份可用。
结语
API 接口安全不是单一层面的问题。XSS 需要前端在渲染时保持警惕,SQL 注入要求后端坚持参数化查询,而服务器加固则是兜底。三者缺一不可。安全工作的性价比很高——今天花一小时加上参数化查询和 SSH 密钥登录,可能就避免了一次导致数据泄露的入侵。建议把上述清单转化为团队的安全检查项,在每次上线前逐条确认。
未经允许不得转载:任鹏个人博客 » API 接口安全中的 XSS 与注入风险:从代码到服务器的完整防线


朋友圈点赞图在线生成源码