优化登录接口以及中间件

This commit is contained in:
2026-03-05 16:20:18 +08:00
parent e5f83846b3
commit 39955a17a8
12 changed files with 268 additions and 516 deletions

View File

@@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace app\api\middleware;
use app\api\cache\UserCache;
use app\api\util\ReturnCode;
use app\dice\model\player\DicePlayer;
use plugin\saiadmin\exception\ApiException;
use Tinywan\Jwt\JwtToken;
use Tinywan\Jwt\Exception\JwtTokenException;
use Tinywan\Jwt\Exception\JwtTokenExpiredException;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
/**
* 校验 token 请求头JWT
* 解码 JWT 取 username与 Redis 中当前有效 token 比对;不一致则旧 token 已失效,请重新登录
* 通过后注入 request->player_id、request->player
*/
class TokenMiddleware implements MiddlewareInterface
{
public function process(Request $request, callable $handler): Response
{
$token = $request->header('token');
if ($token === null || $token === '') {
$auth = $request->header('authorization');
if ($auth && stripos($auth, 'Bearer ') === 0) {
$token = trim(substr($auth, 7));
}
}
$token = $token !== null ? trim((string) $token) : '';
if ($token === '') {
throw new ApiException('请携带 token', ReturnCode::UNAUTHORIZED);
}
try {
$decoded = JwtToken::verify(1, $token);
} catch (JwtTokenExpiredException $e) {
throw new ApiException('token 已过期,请重新登录', ReturnCode::TOKEN_INVALID);
} catch (JwtTokenException $e) {
throw new ApiException('token 无效', ReturnCode::TOKEN_INVALID);
} catch (\Throwable $e) {
throw new ApiException('token 格式无效', ReturnCode::TOKEN_INVALID);
}
$extend = $decoded['extend'] ?? [];
if ((string) ($extend['plat'] ?? '') !== 'api_login') {
throw new ApiException('token 无效', ReturnCode::TOKEN_INVALID);
}
$username = trim((string) ($extend['username'] ?? ''));
if ($username === '') {
throw new ApiException('token 无效', ReturnCode::TOKEN_INVALID);
}
$currentToken = UserCache::getSessionTokenByUsername($username);
if ($currentToken === null || $currentToken === '') {
$player = DicePlayer::where('username', $username)->find();
if (!$player) {
throw new ApiException('请注册', ReturnCode::TOKEN_INVALID);
}
throw new ApiException('请重新登录', ReturnCode::TOKEN_INVALID);
}
if ($currentToken !== $token) {
throw new ApiException('请重新登录(当前账号已在其他处登录)', ReturnCode::TOKEN_INVALID);
}
$player = DicePlayer::where('username', $username)->find();
if (!$player) {
UserCache::deleteSessionByUsername($username);
throw new ApiException('请重新登录', ReturnCode::TOKEN_INVALID);
}
$request->player_id = (int) $player->id;
$request->player = $player;
return $handler($request);
}
}