PHP 怎么PHP 签名URL

wen PHP项目 3

本文目录导读:

PHP 怎么PHP 签名URL

  1. 简单防盗链签名(MD5 + 时间戳)
  2. HMAC-SHA1 签名(更安全,常见于 API)
  3. 阿里云 CDN URL 鉴权(A/B/C/D 类)
  4. 腾讯云 CDN URL 鉴权(时间戳防盗链)
  5. 总结建议

在 PHP 中生成签名 URL(通常用于实现 URL 防盗链、API 鉴权或 CDN 认证),常见的方法有两大类:

  1. 简单的对称加密签名(如 md5/timestamp 组合)
  2. 基于密钥的哈希签名(如 HMAC-SHA1)
  3. 阿里云/腾讯云等云服务商的 A/B 鉴权签名

下面给出这几种常见场景的 PHP 实现代码。


简单防盗链签名(MD5 + 时间戳)

常用于保护静态资源(如图片、视频),防止直接访问。

function signUrl(string $baseUrl, string $secretKey, int $expireTime = 3600): string
{
    // 1. 生成过期时间戳
    $expiration = time() + $expireTime;
    // 2. 拼接待签名字符串(可加入路径、IP限制等)
    $stringToSign = $baseUrl . '-' . $expiration . '-' . $secretKey;
    // 3. 计算签名
    $signature = md5($stringToSign);
    // 4. 拼接签名参数
    $signedUrl = $baseUrl . '?sign=' . $signature . '&expire=' . $expiration;
    return $signedUrl;
}
// 使用示例
$url = 'http://example.com/files/video.mp4';
$key = 'MySecretKey123';
$signedUrl = signUrl($url, $key, 1800); // 30分钟有效
echo $signedUrl;

验证端(服务端)

function verifySignedUrl(string $url, string $secretKey): bool
{
    $parsed = parse_url($url);
    parse_str($parsed['query'] ?? '', $query);
    $sign = $query['sign'] ?? '';
    $expire = $query['expire'] ?? 0;
    // 1. 过期判断
    if (time() > $expire) return false;
    // 2. 重新计算签名
    $basePath = $parsed['scheme'] . '://' . $parsed['host'] . $parsed['path'];
    $stringToSign = $basePath . '-' . $expire . '-' . $secretKey;
    $expectedSign = md5($stringToSign);
    // 3. 比较签名(防止时序攻击)
    return hash_equals($expectedSign, $sign);
}

HMAC-SHA1 签名(更安全,常见于 API)

HMAC 配合 SHA1/SHA256 更安全,常用于 OAuth 或云 API 签名。

function signUrlHmac(string $uri, array $params, string $secretKey): string
{
    // 1. 按参数名排序
    ksort($params);
    // 2. 拼接查询字符串
    $queryString = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
    // 3. 构建待签字符串(通常包含 HTTP 方法+路径+查询字符串)
    $stringToSign = "GET\n{$uri}\n{$queryString}";
    // 4. 计算 HMAC-SHA1 并 base64 编码
    $signature = base64_encode(
        hash_hmac('sha1', $stringToSign, $secretKey, true)
    );
    // 5. 将签名加入参数
    $params['signature'] = $signature;
    return $uri . '?' . http_build_query($params);
}
// 使用示例
$baseUri = '/api/v1/users';
$params = [
    'uid' => 123,
    'timestamp' => time(),
];
$secret = 'my-hmac-key';
$signedUrl = signUrlHmac($baseUri, $params, $secret);
echo "http://api.example.com" . $signedUrl;

阿里云 CDN URL 鉴权(A/B/C/D 类)

以阿里云 CDN 鉴权方式 C(最常见)为例:

原理

签名串 = md5(key + uri + expire_timestamp)
URL = http://domain/path?auth_key=expire-uid-rand-md5

PHP 实现

function aliyunCdnSign(string $path, string $key, int $expireTime, string $uid = '0', string $rand = ''): string
{
    $timestamp = time() + $expireTime;
    $rand = $rand ?: random_int(100000, 999999);
    // 拼接待签字符串: key + path + timestamp
    $stringToSign = $key . $path . $timestamp;
    $md5 = md5($stringToSign);
    // 生成 auth_key 参数
    $authKey = "{$timestamp}-{$uid}-{$rand}-{$md5}";
    return $path . '?auth_key=' . $authKey;
}
// 使用示例
$path = '/files/1.jpg';
$key = 'aliyun_cdn_secret';
$url = aliyunCdnSign($path, $key, 3600);
echo "http://cdn.example.com{$url}";

验证端(CDN 边缘节点自动验证,或你也可以自己写):

function verifyAliyunCdn(string $fullUrl, string $key): bool
{
    $parts = parse_url($fullUrl);
    parse_str($parts['query'] ?? '', $query);
    $authKey = $query['auth_key'] ?? '';
    $segments = explode('-', $authKey);
    if (count($segments) !== 4) return false;
    [$expire, $uid, $rand, $sign] = $segments;
    // 过期判断
    if (time() > intval($expire)) return false;
    // 重新计算签名
    $reSign = md5($key . $parts['path'] . $expire);
    return hash_equals($reSign, $sign);
}

腾讯云 CDN URL 鉴权(时间戳防盗链)

腾讯云常用的 t=(时间戳) + key= 方式:

function tencentCdnSign(string $path, string $key, int $expireTime): string
{
    // 1. 生成过期 Unix 时间戳(十进制)
    $expire = time() + $expireTime;
    // 2. 拼接待签字符串: path + key + t
    $stringToSign = $path . $key . $expire;
    // 3. 计算 md5
    $sign = md5($stringToSign);
    // 4. 拼接到 URL
    return $path . "?t={$expire}&key={$sign}";
}
// 使用示例
echo tencentCdnSign('/resource/1.mp4', 'my_key', 1800);

总结建议

场景 推荐签名方式 关键点
简单 URL 防盗链 MD5 + timestamp 容易实现,但安全性一般
高安全 API/文件 HMAC-SHA1/SHA256 防篡改,防重放
阿里云 CDN 方式 C(auth_key) 注意待签字符串顺序
腾讯云 CDN key + t 模式 注意 t 是十进制时间戳

重要

  • 所有签名密钥应妥善保存(环境变量或配置文件,不出现在代码中)。
  • 建议使用 hash_equals() 比较签名,防止时序攻击。
  • 时间戳验证时注意时区(统一使用 UTC/Unix 时间戳)。

抱歉,评论功能暂时关闭!