feat(security): shorten download signed URLs to 30s and remove update polling

This commit is contained in:
2026-02-18 21:59:14 +08:00
parent c83d9304ea
commit f96a9ccaa9
2 changed files with 21 additions and 85 deletions

View File

@@ -97,6 +97,10 @@ const DOWNLOAD_RESERVATION_TTL_MS = Number(process.env.DOWNLOAD_RESERVATION_TTL_
const DOWNLOAD_LOG_RECONCILE_INTERVAL_MS = Number(process.env.DOWNLOAD_LOG_RECONCILE_INTERVAL_MS || (5 * 60 * 1000)); // 5分钟
const DOWNLOAD_LOG_MAX_FILES_PER_SWEEP = Number(process.env.DOWNLOAD_LOG_MAX_FILES_PER_SWEEP || 40);
const DOWNLOAD_LOG_LIST_MAX_KEYS = Number(process.env.DOWNLOAD_LOG_LIST_MAX_KEYS || 200);
const DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS = Math.max(
10,
Math.min(3600, Number(process.env.DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS || 30))
);
const DEFAULT_DESKTOP_VERSION = process.env.DESKTOP_LATEST_VERSION || '0.1.1';
const DEFAULT_DESKTOP_INSTALLER_URL = process.env.DESKTOP_INSTALLER_URL || '';
const DEFAULT_DESKTOP_RELEASE_NOTES = process.env.DESKTOP_RELEASE_NOTES || '';
@@ -6433,8 +6437,10 @@ app.get('/api/files/download-url', authMiddleware, async (req, res) => {
};
const command = new GetObjectCommand(commandInput);
// 生成签名 URL1小时有效)
const signedUrl = await getSignedUrl(client, command, { expiresIn: 3600 });
// 生成签名 URL时有效默认30秒
const signedUrl = await getSignedUrl(client, command, {
expiresIn: DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS
});
// 直连模式:先预扣保留额度(不写入已用),实际用量由 OSS 日志异步确认入账
if (!trafficState.isUnlimited && fileSize > 0) {
@@ -6454,7 +6460,7 @@ app.get('/api/files/download-url', authMiddleware, async (req, res) => {
res.json({
success: true,
downloadUrl: signedUrl,
expiresIn: 3600,
expiresIn: DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS,
direct: true,
quotaLimited: !trafficState.isUnlimited
});
@@ -8262,8 +8268,10 @@ app.post('/api/share/:code/download-url', shareRateLimitMiddleware, async (req,
ResponseContentDisposition: `attachment; filename="${encodeURIComponent(normalizedFilePath.split('/').pop())}"`
});
// 生成签名 URL1小时有效)
const signedUrl = await getSignedUrl(client, command, { expiresIn: 3600 });
// 生成签名 URL时有效默认30秒
const signedUrl = await getSignedUrl(client, command, {
expiresIn: DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS
});
if (!ownerTrafficState.isUnlimited && fileSize > 0) {
const reserveResult = reserveDirectDownloadTraffic(shareOwner.id, fileSize, {
@@ -8284,7 +8292,7 @@ app.post('/api/share/:code/download-url', shareRateLimitMiddleware, async (req,
downloadUrl: signedUrl,
direct: true,
quotaLimited: !ownerTrafficState.isUnlimited,
expiresIn: 3600
expiresIn: DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS
});
} catch (error) {
@@ -10588,7 +10596,9 @@ app.get('/d/:code', async (req, res) => {
ResponseContentDisposition: `attachment; filename*=UTF-8''${encodeURIComponent(directFileName)}`
});
const signedUrl = await getSignedUrl(client, command, { expiresIn: 3600 });
const signedUrl = await getSignedUrl(client, command, {
expiresIn: DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS
});
DirectLinkDB.incrementDownloadCount(code);
logShare(