fix: harden cloud storage security
This commit is contained in:
@@ -1,10 +1,27 @@
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
const { UserDB, DeviceSessionDB } = require('./database');
|
||||
const { UserDB, DeviceSessionDB, SystemLogDB } = require('./database');
|
||||
const { decryptSecret } = require('./utils/encryption');
|
||||
const DEFAULT_LOCAL_STORAGE_QUOTA_BYTES = 1024 * 1024 * 1024; // 1GB
|
||||
const DEFAULT_OSS_STORAGE_QUOTA_BYTES = 1024 * 1024 * 1024; // 1GB
|
||||
|
||||
function normalizeDownloadTrafficQuotaForAuth(rawQuota) {
|
||||
if (rawQuota === null || rawQuota === undefined || rawQuota === '') {
|
||||
return -1; // 未设置时默认不限流量
|
||||
}
|
||||
|
||||
const parsedQuota = Number(rawQuota);
|
||||
if (!Number.isFinite(parsedQuota)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parsedQuota < 0) {
|
||||
return -1; // -1 表示不限流量
|
||||
}
|
||||
|
||||
return Math.max(0, Math.floor(parsedQuota)); // 0 表示禁止下载
|
||||
}
|
||||
|
||||
// JWT密钥(必须在环境变量中设置)
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
|
||||
// Refresh Token密钥(使用不同的密钥)
|
||||
@@ -17,7 +34,8 @@ const REFRESH_TOKEN_EXPIRES = '7d'; // Refresh token 7天
|
||||
// 安全检查:验证JWT密钥配置
|
||||
const DEFAULT_SECRETS = [
|
||||
'your-secret-key-change-in-production',
|
||||
'your-secret-key-change-in-production-PLEASE-CHANGE-THIS'
|
||||
'your-secret-key-change-in-production-PLEASE-CHANGE-THIS',
|
||||
'your-secret-key-PLEASE-CHANGE-THIS-IN-PRODUCTION'
|
||||
];
|
||||
|
||||
// 安全修复:增强 JWT_SECRET 验证逻辑
|
||||
@@ -234,10 +252,7 @@ function authMiddleware(req, res, next) {
|
||||
const effectiveOssQuota = Number.isFinite(rawOssQuota) && rawOssQuota > 0
|
||||
? rawOssQuota
|
||||
: DEFAULT_OSS_STORAGE_QUOTA_BYTES;
|
||||
const rawDownloadTrafficQuota = Number(user.download_traffic_quota);
|
||||
const effectiveDownloadTrafficQuota = Number.isFinite(rawDownloadTrafficQuota) && rawDownloadTrafficQuota > 0
|
||||
? Math.floor(rawDownloadTrafficQuota)
|
||||
: 0; // 0 表示不限流量
|
||||
const effectiveDownloadTrafficQuota = normalizeDownloadTrafficQuotaForAuth(user.download_traffic_quota);
|
||||
const rawDownloadTrafficUsed = Number(user.download_traffic_used);
|
||||
const normalizedDownloadTrafficUsed = Number.isFinite(rawDownloadTrafficUsed) && rawDownloadTrafficUsed > 0
|
||||
? Math.floor(rawDownloadTrafficUsed)
|
||||
@@ -257,8 +272,6 @@ function authMiddleware(req, res, next) {
|
||||
oss_provider: user.oss_provider,
|
||||
oss_region: user.oss_region,
|
||||
oss_access_key_id: user.oss_access_key_id,
|
||||
// 安全修复:解密 OSS Access Key Secret(如果存在)
|
||||
oss_access_key_secret: user.oss_access_key_secret ? decryptSecret(user.oss_access_key_secret) : null,
|
||||
oss_bucket: user.oss_bucket,
|
||||
oss_endpoint: user.oss_endpoint,
|
||||
// 存储相关字段
|
||||
@@ -276,6 +289,12 @@ function authMiddleware(req, res, next) {
|
||||
// 主题偏好
|
||||
theme_preference: user.theme_preference || null
|
||||
};
|
||||
Object.defineProperty(req.user, 'oss_access_key_secret', {
|
||||
value: user.oss_access_key_secret ? decryptSecret(user.oss_access_key_secret) : null,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false
|
||||
});
|
||||
req.authSessionId = sessionId || null;
|
||||
req.authTokenJti = typeof decoded.jti === 'string' ? decoded.jti : null;
|
||||
|
||||
@@ -321,14 +340,21 @@ function adminMiddleware(req, res, next) {
|
||||
* );
|
||||
*/
|
||||
function requirePasswordConfirmation(req, res, next) {
|
||||
const { password } = req.body;
|
||||
const password = String(
|
||||
req.body?.current_password ||
|
||||
req.body?.admin_password ||
|
||||
req.body?.password_confirmation ||
|
||||
req.body?.password ||
|
||||
''
|
||||
);
|
||||
|
||||
// 检查是否提供了密码
|
||||
if (!password) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '执行此操作需要验证密码',
|
||||
require_password: true
|
||||
require_password: true,
|
||||
requirePasswordConfirmation: true
|
||||
});
|
||||
}
|
||||
|
||||
@@ -355,7 +381,6 @@ function requirePasswordConfirmation(req, res, next) {
|
||||
|
||||
if (!isPasswordValid) {
|
||||
// 记录安全日志:密码验证失败
|
||||
SystemLogDB = require('./database').SystemLogDB;
|
||||
SystemLogDB.log({
|
||||
level: SystemLogDB.LEVELS.WARN,
|
||||
category: SystemLogDB.CATEGORIES.SECURITY,
|
||||
|
||||
Reference in New Issue
Block a user