Files
lotteryLaravel/app/Support/PlayerTokenAesUnwrap.php
kang c9c1fecfcf feat(player-auth): add JWT TTL check and AES wrapped token support
1. 新增JWT有效期校验,限制exp-iat最大时长并支持强制校验iat字段
2. 新增AES-GCM密文Token解包能力,支持非标准JWT格式的令牌传递
3. 新增相关配置项和环境变量,可灵活调整校验策略
2026-05-14 09:37:52 +08:00

56 lines
1.6 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Support;
/**
* URL/Query 传入的 AES-256-GCM 密文 Token 解包为内层 JWT 明文字符串。
*
* 约定Base64( IV(12) ‖ ciphertext ‖ tag(16) ),明文为 UTF-8 JWT三点分段
* 密钥:`config('lottery.player_auth.aes.key_base64')` Base64 解码后为 32 字节。
*/
final class PlayerTokenAesUnwrap
{
/**
* @return 内层 JWT 或 null未启用/格式错/解密失败)
*/
public static function tryUnwrap(string $opaque): ?string
{
$keyB64 = config('lottery.player_auth.aes.key_base64');
if (! is_string($keyB64) || trim($keyB64) === '') {
return null;
}
$keyRaw = base64_decode(trim($keyB64), true);
if (! is_string($keyRaw) || strlen($keyRaw) !== 32) {
return null;
}
$trim = trim($opaque);
if ($trim === '') {
return null;
}
$bin = base64_decode(strtr($trim, '-_', '+/'), true);
if ($bin === false || strlen($bin) < 12 + 1 + 16) {
return null;
}
$iv = substr($bin, 0, 12);
$tag = substr($bin, -16);
$cipher = substr($bin, 12, -16);
$plain = openssl_decrypt($cipher, 'aes-256-gcm', $keyRaw, OPENSSL_RAW_DATA, $iv, $tag);
if (! is_string($plain) || $plain === '') {
return null;
}
return self::looksLikeJwt($plain) ? $plain : null;
}
private static function looksLikeJwt(string $s): bool
{
return preg_match('/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/', $s) === 1;
}
}