Files
dafuweng-saiadmin6.x/server/app/api/controller/AuthTokenController.php
2026-03-05 13:44:56 +08:00

91 lines
3.2 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\api\controller;
use support\Request;
use support\Response;
use Tinywan\Jwt\JwtToken;
use plugin\saiadmin\basic\OpenController;
use app\api\util\ReturnCode;
use app\api\cache\AuthTokenCache;
/**
* API 鉴权 Token 接口
* 仅支持 GET必传参数signature、secret、device、time签名规则signature = md5(device . secret . time)
* 后续所有 /api 接口调用均需在请求头携带此接口返回的 auth-token
*/
class AuthTokenController extends OpenController
{
/**
* 获取 auth-token
* GET /api/authToken
* 参数signature签名、secret密钥、device设备标识、time时间戳四者均为必传且非空
*/
public function index(Request $request): Response
{
if (strtoupper($request->method()) !== 'GET') {
return $this->fail('仅支持 GET 请求', ReturnCode::PARAMS_ERROR);
}
$param = $request->get();
$signature = trim((string) ($param['signature'] ?? ''));
$secret = trim((string) ($param['secret'] ?? ''));
$device = trim((string) ($param['device'] ?? ''));
$time = trim((string) ($param['time'] ?? ''));
if ($signature === '' || $secret === '' || $device === '' || $time === '') {
return $this->fail('signature、secret、device、time 均为必传且不能为空', ReturnCode::PARAMS_ERROR);
}
$serverSecret = trim((string) config('api.auth_token_secret', ''));
if ($serverSecret === '') {
return $this->fail('服务未配置 API_AUTH_TOKEN_SECRET', ReturnCode::PARAMS_ERROR);
}
if ($secret !== $serverSecret) {
return $this->fail('密钥错误', ReturnCode::FORBIDDEN);
}
$tolerance = (int) config('api.auth_token_time_tolerance', 300);
$now = time();
$ts = is_numeric($time) ? (int) $time : 0;
if ($ts <= 0 || abs($now - $ts) > $tolerance) {
return $this->fail('时间戳无效或已过期', ReturnCode::PARAMS_ERROR);
}
$sign = $this->getAuthToken($device, $serverSecret, $time);
if ($sign !== $signature) {
return $this->fail('签名验证失败', ReturnCode::FORBIDDEN);
}
$exp = (int) config('api.auth_token_exp', 86400);
$tokenResult = JwtToken::generateToken([
'id' => 0,
'plat' => 'api',
'device' => $device,
'access_exp' => $exp,
]);
// 同一设备只保留最新 token覆盖后旧 token 失效
AuthTokenCache::setDeviceToken($device, $tokenResult['access_token'], $exp);
return $this->success([
'auth-token' => $tokenResult['access_token'],
'expires_in' => $tokenResult['expires_in'],
]);
}
/**
* 生成签名signature = md5(device . secret . time)
*
* @param string $device 设备标识
* @param string $secret 密钥(来自配置)
* @param string $time 时间戳
* @return string
*/
private function getAuthToken(string $device, string $secret, string $time): string
{
return md5($device . $secret . $time);
}
}