This commit is contained in:
陈思海 2026-02-09 14:21:53 +08:00
parent 9417e7b467
commit d209934e69

View File

@ -64,7 +64,8 @@ async function getVideoCoverFromVod(fileId) {
// 生成VOD防盗链签名URL // 生成VOD防盗链签名URL
// 根据腾讯云文档https://cloud.tencent.com/document/product/266/14047 // 根据腾讯云文档https://cloud.tencent.com/document/product/266/14047
// 签名算法sign = MD5(KEY + Dir + t + us) // 签名算法sign = MD5(KEY + Dir + t + us)
function generateSignedUrl(videoUrl, signKey, expirationTime = 86400) { // enableLog: 控制是否输出日志,默认从环境变量 VOD_SIGN_LOG 读取(值为'true'时启用),或直接传入 true/false
function generateSignedUrl(videoUrl, signKey, expirationTime = 86400, requestDomain = '', enableLog = process.env.VOD_SIGN_LOG === 'true') {
if (!signKey || !videoUrl) { if (!signKey || !videoUrl) {
return videoUrl; return videoUrl;
} }
@ -80,7 +81,8 @@ function generateSignedUrl(videoUrl, signKey, expirationTime = 86400) {
const dir = pathname.substring(0, lastSlashIndex + 1); const dir = pathname.substring(0, lastSlashIndex + 1);
// 计算过期时间戳(十六进制小写) // 计算过期时间戳(十六进制小写)
const expirationTimestamp = Math.floor(Date.now() / 1000) + expirationTime; const now = Date.now();
const expirationTimestamp = Math.floor(now / 1000) + expirationTime;
const t = expirationTimestamp.toString(16).toLowerCase(); const t = expirationTimestamp.toString(16).toLowerCase();
// 生成随机字符串10位 // 生成随机字符串10位
@ -93,15 +95,34 @@ function generateSignedUrl(videoUrl, signKey, expirationTime = 86400) {
// 拼接最终URL参数顺序必须是t, us, sign // 拼接最终URL参数顺序必须是t, us, sign
const signedUrl = `${videoUrl}?t=${t}&us=${us}&sign=${sign}`; const signedUrl = `${videoUrl}?t=${t}&us=${us}&sign=${sign}`;
// console.log('=== VOD签名调试信息 ==='); // 如果启用日志输出,则输出详细信息
// console.log('原始URL:', videoUrl); if (enableLog) {
// console.log('Dir路径:', dir); const formatTime = (timestamp) => {
// console.log('过期时间t:', t); return new Date(timestamp).toLocaleString('zh-CN', {
// console.log('随机字符串us:', us); timeZone: 'Asia/Shanghai',
// console.log('签名字符串:', signString); year: 'numeric',
// console.log('MD5签名:', sign); month: '2-digit',
// console.log('最终URL:', signedUrl); day: '2-digit',
// console.log('====================='); hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
};
const videoDomain = `${url.protocol}//${url.host}`;
console.log('=== VOD签名信息 ===');
console.log('当前请求域名:', requestDomain || '未提供');
console.log('视频URL域名:', videoDomain);
console.log('当前时间:', formatTime(now));
console.log('当前时间戳:', Math.floor(now / 1000));
console.log('链接过期时间:', formatTime(expirationTimestamp * 1000));
console.log('有效时长:', expirationTime, '秒 (', Math.floor(expirationTime / 3600), '小时)');
console.log('原始URL:', videoUrl);
console.log('签名后URL:', signedUrl);
console.log('==================\n');
}
return signedUrl; return signedUrl;
} catch (error) { } catch (error) {
@ -245,6 +266,9 @@ const upload = multer({
// 获取所有活跃视频(前台使用) // 获取所有活跃视频(前台使用)
router.get('/public', async (req, res) => { router.get('/public', async (req, res) => {
try { try {
// 获取当前请求的域名
const requestDomain = `${req.protocol}://${req.get('host')}`;
// 获取VOD配置以获取签名密钥 // 获取VOD配置以获取签名密钥
const [configs] = await db.query('SELECT sign_key FROM vod_config LIMIT 1'); const [configs] = await db.query('SELECT sign_key FROM vod_config LIMIT 1');
const signKey = configs.length > 0 ? configs[0].sign_key : null; const signKey = configs.length > 0 ? configs[0].sign_key : null;
@ -256,7 +280,7 @@ router.get('/public', async (req, res) => {
// 为每个视频URL生成签名 // 为每个视频URL生成签名
const videosWithSignedUrls = videos.map(video => { const videosWithSignedUrls = videos.map(video => {
if (video.video_url && signKey) { if (video.video_url && signKey) {
video.video_url = generateSignedUrl(video.video_url, signKey); video.video_url = generateSignedUrl(video.video_url, signKey, 86400, requestDomain);
} }
return video; return video;
}); });