1. 选择合适的日志库
使用专业的日志库(如Winston、Bunyan)替代原生console模块,这些库支持日志级别管理(如error、warn、info分级)、多输出目标(文件、数据库、远程服务器)及结构化日志(JSON格式),便于后续分析和过滤敏感信息。例如,Winston可通过transports配置将日志写入不同位置,Bunyan则自带JSON格式化功能。
2. 敏感信息过滤与环境变量管理
避免在日志中直接输出敏感数据(如API密钥、数据库密码、用户隐私信息)。使用.env文件存储敏感数据,通过dotenv库在应用中加载,并将.env添加到.gitignore以防止提交到版本控制系统。例如:
require('dotenv').config();
const apiKey = process.env.API_KEY; // 从环境变量读取,而非硬编码
logger.info(`API Key: ${apiKey}`); // 避免直接输出敏感值
同时,可通过日志库的format选项过滤敏感字段(如Winston的replace函数替换敏感内容)。
3. 日志轮转与清理
使用logrotate工具定期轮换日志文件,防止单个文件过大导致磁盘空间耗尽,同时便于归档和检索。创建/etc/logrotate.d/nodejs配置文件,示例如下:
/var/log/my-node-app/*.log {
daily # 每天轮转
missingok # 忽略缺失文件
rotate 14 # 保留14天日志
compress # 压缩旧日志(gzip)
delaycompress # 延迟压缩(避免压缩当天日志)
notifempty # 空日志不轮转
create 640 nodeapp nodeapp # 新日志文件权限与所有者
sharedscripts # 所有日志轮转完成后执行脚本
postrotate
[ ! -f /var/run/my-node-app.pid ] || kill -USR1 `cat /var/run/my-node-app.pid` # 通知应用重新打开日志文件
endscript
}
此配置确保日志每日轮转,保留14天,压缩旧日志,并通过postrotate脚本通知应用(如PM2、Node.js原生)重新打开日志文件,避免日志丢失。
4. 访问控制与权限管理
遵循最小权限原则,为日志文件和目录设置严格权限:
nodeapp)和组(如nodeapp)运行Node.js应用:sudo groupadd nodeapp
sudo useradd -g nodeapp -s /bin/false nodeapp
/var/log/my-node-app)的所有者设为nodeapp,权限设为750(所有者可读写执行,组可读执行,其他用户无权限):sudo mkdir -p /var/log/my-node-app
sudo chown nodeapp:nodeapp /var/log/my-node-app
sudo chmod 750 /var/log/my-node-app
fs.createWriteStream设置文件权限为0o640(所有者可读写,组可读):const fs = require('fs');
const logStream = fs.createWriteStream('/var/log/my-node-app/app.log', {
flags: 'a',
mode: 0o640 // 设置文件权限
});
避免使用root用户运行应用,降低权限滥用风险。5. 日志加密存储
对敏感日志(如包含用户隐私、财务数据的日志)进行加密,即使日志文件被非法访问,也无法直接读取内容。可使用crypto模块(Node.js原生)或GPG工具:
crypto模块加密:const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const key = crypto.scryptSync('my-secret-key', 'salt', 32); // 密钥(需安全存储)
const iv = crypto.randomBytes(16); // 初始化向量
function encrypt(text) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 写入加密日志
const encryptedLog = encrypt('Sensitive data: user password');
fs.appendFileSync('/var/log/my-node-app/sensitive.log', encryptedLog + '\n');
GPG加密:生成密钥对,用公钥加密日志文件,只有私钥持有者可解密。可结合logrotate的postrotate脚本,在日志轮转后自动加密新日志并删除原始文件。6. 集中式日志管理
将日志发送到集中式日志管理系统(如ELK Stack:Elasticsearch+Logstash+Kibana、Graylog、Splunk),实现统一存储、搜索、分析和报警。通过rsyslog或syslog-ng配置日志传输:
rsyslog客户端:sudo apt install rsyslog/etc/rsyslog.conf,添加以下内容(UDP传输,端口514):*.* @<syslog-server-ip>:514
或TCP传输(更可靠):*.* @@<syslog-server-ip>:514
rsyslog服务:sudo systemctl restart rsyslogrsyslog的imudp模块),并存储到指定目录。集中式管理便于监控全局日志,及时发现异常(如大量error日志)。7. 日志监控与审计
实施日志监控,使用工具(如Prometheus+Grafana、Zabbix、Nagios)监控日志文件的大小、增长速度、内容异常(如频繁的error日志),及时发出报警。同时,定期审计日志,检查是否有未授权访问、异常操作(如大量失败登录尝试)或敏感信息泄露(如密码出现在日志中)。例如,通过grep命令查找error日志:
grep 'error' /var/log/my-node-app/*.log
或使用awk统计错误数量:
awk '/error/ {count++} END {print count}' /var/log/my-node-app/*.log
审计结果可用于优化应用安全策略(如修复导致大量错误的漏洞)。