跳转至

A 模式签名规则(md5-timestamp-rand)

概述

A 模式是基于 MD5 哈希算法的鉴权方式,通过时间戳和随机字符串确保签名的唯一性和时效性。

签名格式

A 模式的签名格式如下:

signature = md5hash-timestamp-rand

鉴权字段说明

字段 说明
timestamp 秒级 Unix 时间戳(整数)。
Path 请求路径(不包含参数,例如https://test.com/demo.js?id=1234中的/demo.js)。
rand 0 - 100 位随机字符串,由大小写字母与数字组成。
secret 客户端持有的鉴权密钥,必须在服务端 密钥 列表中。
md5hash 明文的 MD5 值(32 位小写),md5hash = md5(Path-timestamp-rand-secret)。

获取鉴权参数

  • Path:/demo.js。
  • timestamp:服务端生成鉴权 URL 的时间为2024年7月15日 15:27:17(UTC+8),转换为十进制(Unix 时间戳)格式的数值为1721028437。
  • rand:生成随机数为 Kv4cPTAAP5YTi。
  • 密钥:DvYmqE81E1F9R791H6lmht。
  • md5hash:MD5(Path-timestamp-rand-密钥)= MD5(/demo.js-1721028437-Kv4cPTAAP5YTi-DvYmqE81E1F9R791H6lmht)= 0fbdca749d7ab784750685347e42075c。

客户端请求示例

GET /demo.js HTTP/1.1
Host: test.com
x-security-auth: 0fbdca749d7ab784750685347e42075c-1721028437-Kv4cPTAAP5YTi

节点鉴权

当节点服务器接收到客户端通过加密 URL 发出的请求时,解析出 signature 中的 timestamp 参数,加上配置的有效时长“1秒”,与当前时间比较:
1. 若当前时间超过“timestamp + 有效时长”时间,则为过期请求,直接返回418。若当前时间未超过“timestamp + 有效时长”时间,则请求未过期,继续第 2 步。
2. 节点服务器通过获取的鉴权参数计算 md5hash 值,与请求 signature 中携带的 md5hash 值做比较:两值相同,鉴权通过,响应请求;两值不同,鉴权失败,返回 418。

JavaScript 实现示例

/**
 * 生成 A 模式 signature
 * @param {string} uri 请求路径,例如 "/demo.js"
 * @param {string} secret 鉴权密钥
 * @returns {Promise<string>} 生成的签名字符串
 */
async function generateSignatureTypeA(uri, secret) {
  // 1. 获取当前秒级时间戳
  const timestamp = Math.floor(Date.now() / 1000);

  // 2. 生成 12 位随机字符串
  const rand = randomString(12);

  // 3. 按照规则拼接明文
  const plaintext = `${uri}-${timestamp}-${rand}-${secret}`;

  // 4. 计算明文的 MD5 值(32 位小写)
  const md5hex = await md5Hex(plaintext);

  // 5. 组合生成最终的 signature
  return `${md5hex}-${timestamp}-${rand}`;
}

/**
 * 生成指定长度的随机字符串
 * @param {number} length 字符串长度,默认 12
 * @returns {string} 随机字符串
 */
function randomString(length = 12) {
  const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const bytes = new Uint8Array(length);
  crypto.getRandomValues(bytes);
  let out = "";
  for (let i = 0; i < length; i++) {
    out += chars[bytes[i] % chars.length];
  }
  return out;
}

/**
 * MD5 哈希函数实现
 * @param {string} input 输入字符串
 * @returns {Promise<string>} MD5 哈希值(32 位小写)
 * @note 请替换为项目中实际使用的 MD5 实现,例如 crypto-js、blueimp-md5 等库
 */
async function md5Hex(input) {
  return md5(input).toLowerCase(); 
}