Node.js安全实践
介绍
Node.js作为一种流行的服务器端JavaScript运行环境,其安全性至关重要。本章将介绍Node.js应用开发中的安全最佳实践,帮助开发者构建更安全的应用程序。
核心安全原则
- 最小权限原则:只授予应用程序完成其功能所需的最小权限
- 输入验证:验证所有用户输入,不信任任何外部数据
- 输出编码:对所有输出到客户端的数据进行适当编码
- 防御深度:实施多层安全措施,不要依赖单一防线
- 安全默认配置:使用安全的默认设置,避免不安全的配置
- 保持更新:及时更新Node.js版本和依赖包
- 安全审计:定期进行安全审计和代码审查
常见安全漏洞与防御
1. 注入攻击
包括SQL注入、NoSQL注入和命令注入等。
防御措施
- 使用参数化查询或ORM框架
- 避免使用eval()、exec()等危险函数
- 验证和过滤所有用户输入
代码示例
// 使用mysql2进行参数化查询
const mysql = require('mysql2/promise');
async function getUser(username) {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb'
});
// 参数化查询防止SQL注入
const [rows] = await connection.execute('SELECT * FROM users WHERE username = ?', [username]);
return rows;
}
2. 跨站脚本攻击(XSS)
攻击者将恶意脚本注入到网页中,在用户浏览器中执行。
防御措施
- 使用内容安全策略(CSP)
- 对所有输出到HTML的数据进行编码
- 避免使用innerHTML等直接插入HTML的方法
代码示例
const express = require('express');
const helmet = require('helmet');
const escapeHtml = require('escape-html');
const app = express();
// 设置内容安全策略
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ['\'self\''],
scriptSrc: ['\'self\''],
styleSrc: ['\'self\''],
},
},
}));
// 输出编码示例
app.get('/user/:name', (req, res) => {
const safeName = escapeHtml(req.params.name);
res.send(`Hello, ${safeName}!`);
});
3. 跨站请求伪造(CSRF)
攻击者诱导用户在已认证的网站上执行非本意的操作。
防御措施
- 使用CSRF令牌
- 验证HTTP Referer头
- 实现SameSite Cookie策略
代码示例
const express = require('express');
const cookieParser = require('cookie-parser');
const csurf = require('csurf');
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// 启用CSRF保护
const csrfProtection = csurf({
cookie: {
httpOnly: true,
sameSite: 'strict'
}
});
app.get('/form', csrfProtection, (req, res) => {
// 传递CSRF令牌到表单
res.send(`
<form action="/submit" method="POST">
<input type="hidden" name="_csrf" value=