安全最佳实践 #
一、安全概述 #
1.1 常见安全威胁 #
| 威胁 | 说明 |
|---|---|
| XSS | 跨站脚本攻击 |
| CSRF | 跨站请求伪造 |
| SQL注入 | 恶意SQL代码注入 |
| 点击劫持 | 嵌入恶意iframe |
| 中间人攻击 | 数据传输被窃听 |
1.2 安全原则 #
- 最小权限原则
- 输入验证
- 输出编码
- 使用HTTPS
- 及时更新依赖
二、Helmet安全头 #
2.1 安装 #
bash
npm install helmet
2.2 基本使用 #
javascript
const helmet = require('helmet');
app.use(helmet());
2.3 单独配置 #
javascript
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "trusted-cdn.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "cdn.example.com"],
connectSrc: ["'self'", "api.example.com"],
fontSrc: ["'self'", "fonts.gstatic.com"],
objectSrc: ["'none'"],
frameSrc: ["'none'"],
upgradeInsecureRequests: []
}
}));
app.use(helmet.crossOriginEmbedderPolicy());
app.use(helmet.crossOriginOpenerPolicy());
app.use(helmet.crossOriginResourcePolicy({ policy: "same-origin" }));
app.use(helmet.dnsPrefetchControl({ allow: false }));
app.use(helmet.frameguard({ action: 'deny' }));
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts({ maxAge: 31536000, includeSubDomains: true }));
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.originAgentCluster());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' }));
app.use(helmet.xssFilter());
三、CSRF防护 #
3.1 安装csurf #
bash
npm install csurf cookie-parser
3.2 配置 #
javascript
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.get('/api/csrf-token', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
app.post('/api/data', (req, res) => {
res.json({ message: '成功' });
});
3.3 前端使用 #
javascript
fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(data)
});
四、XSS防护 #
4.1 输入验证 #
javascript
const validator = require('validator');
const sanitizeInput = (input) => {
return validator.escape(input);
};
const validateEmail = (email) => {
return validator.isEmail(email);
};
4.2 输出编码 #
javascript
const escapeHtml = (str) => {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
4.3 Content Security Policy #
javascript
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
frameSrc: ["'none'"]
}
}));
五、SQL注入防护 #
5.1 参数化查询 #
javascript
const [rows] = await pool.query(
'SELECT * FROM users WHERE id = ?',
[userId]
);
5.2 ORM使用 #
javascript
const user = await User.findOne({ where: { id: userId } });
5.3 输入验证 #
javascript
const { body, validationResult } = require('express-validator');
app.post('/users', [
body('name').trim().escape(),
body('email').isEmail().normalizeEmail()
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
});
六、认证安全 #
6.1 密码哈希 #
javascript
const bcrypt = require('bcryptjs');
const hashPassword = async (password) => {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(password, salt);
};
const comparePassword = async (password, hashedPassword) => {
return await bcrypt.compare(password, hashedPassword);
};
6.2 JWT安全 #
javascript
const jwt = require('jsonwebtoken');
const generateToken = (userId) => {
return jwt.sign(
{ id: userId },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
);
};
const verifyToken = (token) => {
return jwt.verify(token, process.env.JWT_SECRET);
};
6.3 速率限制 #
javascript
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: '登录尝试过多,请稍后再试'
});
app.post('/auth/login', loginLimiter, loginHandler);
七、HTTPS配置 #
7.1 强制HTTPS #
javascript
app.use((req, res, next) => {
if (!req.secure && req.get('x-forwarded-proto') !== 'https') {
return res.redirect(`https://${req.get('host')}${req.url}`);
}
next();
});
7.2 HSTS #
javascript
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
八、完整配置 #
javascript
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss-clean');
const hpp = require('hpp');
const app = express();
app.use(helmet());
app.use(cors({
origin: process.env.CORS_ORIGIN,
credentials: true
}));
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
});
app.use('/api', limiter);
app.use(express.json({ limit: '10kb' }));
app.use(mongoSanitize());
app.use(xss());
app.use(hpp());
module.exports = app;
九、总结 #
安全要点:
| 措施 | 说明 |
|---|---|
| Helmet | 安全HTTP头 |
| CSRF | 跨站请求伪造防护 |
| XSS | 跨站脚本防护 |
| 参数化查询 | SQL注入防护 |
| 密码哈希 | 密码安全存储 |
| HTTPS | 加密传输 |
下一步,让我们学习会话管理!
最后更新:2026-03-28