From 4324c19d30bd4511ed983bf3fc618f27aa7e9e92 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Fri, 29 May 2026 14:19:24 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BC=98=E5=8C=96=E8=AE=BE=E5=A4=87=E5=8F=AA?= =?UTF-8?q?=E8=83=BD=E7=99=BB=E5=BD=95=E4=B8=80=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/controller/Account.php | 5 + app/api/controller/Auth.php | 35 +++- app/api/controller/MobileBase.php | 17 +- app/api/controller/V1.php | 2 + app/api/lang/en.php | 1 + app/api/lang/zh-cn.php | 1 + .../service/GameWebSocketAuthHelper.php | 5 + .../service/MobileAuthDeviceService.php | 153 ++++++++++++++++++ 8 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 app/common/service/MobileAuthDeviceService.php diff --git a/app/api/controller/Account.php b/app/api/controller/Account.php index ca8b71b..844cfbf 100644 --- a/app/api/controller/Account.php +++ b/app/api/controller/Account.php @@ -12,6 +12,7 @@ use app\common\model\UserScoreLog; use app\common\model\UserMoneyLog; use app\common\controller\Frontend; use app\common\facade\Token as TokenFacade; +use app\common\service\MobileAuthDeviceService; use support\think\Db; use support\validation\Validator; use support\validation\ValidationException; @@ -44,6 +45,10 @@ class Account extends Frontend $user = $this->auth->getUser(); $userId = intval(strval($user->id)); + $deviceError = MobileAuthDeviceService::validateUserDeviceSession($authToken, $userId); + if ($deviceError !== null) { + return $this->mobileResult(1101, $deviceError); + } $coinBalance = WithdrawFlow::amountString($user->coin ?? '0'); // 打码量 / 提现配额快照 diff --git a/app/api/controller/Auth.php b/app/api/controller/Auth.php index 1c04f8a..7b0c78b 100644 --- a/app/api/controller/Auth.php +++ b/app/api/controller/Auth.php @@ -7,6 +7,7 @@ namespace app\api\controller; use app\common\facade\Token; use app\common\library\Auth as UserAuth; use app\common\model\User; +use app\common\service\MobileAuthDeviceService; use ba\Random; use support\think\Db; use Webman\Http\Request; @@ -83,6 +84,8 @@ class Auth extends MobileBase return $this->mobileError(2000, 'Registered successfully but login failed'); } + $this->bindMobileDeviceSession($request); + return $this->mobileSuccess($this->buildLoginPayload()); } @@ -106,6 +109,9 @@ class Auth extends MobileBase if (!$ok) { return $this->mobileError(1101, 'Incorrect account or password'); } + + $this->bindMobileDeviceSession($request); + return $this->mobileSuccess($this->buildLoginPayload()); } @@ -126,14 +132,41 @@ class Auth extends MobileBase return $this->mobileError(1101, 'Login status has expired'); } + $authToken = trim((string) $request->header('auth-token', '')); + $userId = filter_var($tokenData['user_id'] ?? 0, FILTER_VALIDATE_INT); + if ($userId === false || $userId <= 0) { + return $this->mobileError(1101, 'Login status has expired'); + } + $deviceError = MobileAuthDeviceService::validateUserDeviceSession($authToken, (int) $userId); + if ($deviceError !== null) { + return $this->mobileError(1101, $deviceError); + } + $newToken = Random::uuid(); - Token::set($newToken, UserAuth::TOKEN_TYPE, $tokenData['user_id'], config('buildadmin.user_token_keep_time', 259200)); + Token::set($newToken, UserAuth::TOKEN_TYPE, (int) $userId, config('buildadmin.user_token_keep_time', 259200)); return $this->mobileSuccess([ 'user-token' => $newToken, 'expires_in' => config('buildadmin.user_token_keep_time', 259200), ]); } + private function bindMobileDeviceSession(Request $request): void + { + if (!$this->auth->isLogin()) { + return; + } + $authToken = trim((string) $request->header('auth-token', '')); + if ($authToken === '') { + return; + } + MobileAuthDeviceService::onUserLogin( + (int) $this->auth->id, + $authToken, + $this->auth->getToken(), + $this->auth->getRefreshToken() + ); + } + private function buildLoginPayload(): array { $userInfo = $this->auth->getUserInfo(); diff --git a/app/api/controller/MobileBase.php b/app/api/controller/MobileBase.php index 6ac0a36..e6dc9fb 100644 --- a/app/api/controller/MobileBase.php +++ b/app/api/controller/MobileBase.php @@ -6,6 +6,7 @@ namespace app\api\controller; use app\common\controller\Frontend; use app\common\facade\Token; +use app\common\service\MobileAuthDeviceService; use support\Response; use Webman\Http\Request; use function response; @@ -28,6 +29,7 @@ abstract class MobileBase extends Frontend $parts = explode('/', $path); $action = $parts[array_key_last($parts)] ?? ''; $needAuthToken = !action_in_arr($this->noNeedAuthToken, $action); + $authToken = ''; if ($needAuthToken) { $authToken = trim((string) $request->header('auth-token', '')); if ($authToken === '') { @@ -41,7 +43,20 @@ abstract class MobileBase extends Frontend } } - return $this->initializeFrontend($request); + $response = $this->initializeFrontend($request); + if ($response !== null) { + return $response; + } + + $needLogin = !action_in_arr($this->noNeedLogin, $action); + if ($needAuthToken && $needLogin && $this->auth->isLogin()) { + $deviceError = MobileAuthDeviceService::validateUserDeviceSession($authToken, (int) $this->auth->id); + if ($deviceError !== null) { + return $this->mobileError(1101, $deviceError); + } + } + + return null; } protected function mobileSuccess(array $data = [], string $message = 'ok'): Response diff --git a/app/api/controller/V1.php b/app/api/controller/V1.php index ff401b7..6f03aab 100644 --- a/app/api/controller/V1.php +++ b/app/api/controller/V1.php @@ -6,6 +6,7 @@ namespace app\api\controller; use app\common\controller\Api; use app\common\facade\Token; +use app\common\service\MobileAuthDeviceService; use ba\Random; use Webman\Http\Request; use support\Response; @@ -64,6 +65,7 @@ class V1 extends Api $token = Random::uuid(); $expire = 60 * 60 * 24; Token::set($token, 'auth-token', 0, $expire); + MobileAuthDeviceService::bindAuthTokenDevice($token, $deviceId, $expire); return $this->mobileResult(1, 'ok', [ 'auth_token' => $token, diff --git a/app/api/lang/en.php b/app/api/lang/en.php index de02219..92b8a56 100644 --- a/app/api/lang/en.php +++ b/app/api/lang/en.php @@ -1,6 +1,7 @@ 'Login expired, please login again.', + 'Logged in on another device, please login again.' => 'Your account was logged in on another device. Please sign in again.', 'Account not exist' => 'Account does not exist', 'Account disabled' => 'Account is disabled', 'Token login failed' => 'Token login failed', diff --git a/app/api/lang/zh-cn.php b/app/api/lang/zh-cn.php index 8ecb8b2..7d24038 100644 --- a/app/api/lang/zh-cn.php +++ b/app/api/lang/zh-cn.php @@ -31,6 +31,7 @@ return [ 'Mobile' => '手机号', 'Password' => '密码', 'Login expired, please login again.' => '登录过期,请重新登录。', + 'Logged in on another device, please login again.' => '您的账号已在其他设备登录,请重新登录', 'Account not exist' => '帐户不存在', 'Account disabled' => '帐户已禁用', 'Token login failed' => '令牌登录失败', diff --git a/app/common/service/GameWebSocketAuthHelper.php b/app/common/service/GameWebSocketAuthHelper.php index cb63b0d..e51dfbe 100644 --- a/app/common/service/GameWebSocketAuthHelper.php +++ b/app/common/service/GameWebSocketAuthHelper.php @@ -111,6 +111,11 @@ final class GameWebSocketAuthHelper return self::deny('user-token has no user_id', $authToken, $userToken, ''); } + $deviceError = MobileAuthDeviceService::validateUserDeviceSession($authToken, (int) $userId); + if ($deviceError !== null) { + return self::deny($deviceError, $authToken, $userToken, ''); + } + return [ 'ok' => true, 'user_id' => (int) $userId, diff --git a/app/common/service/MobileAuthDeviceService.php b/app/common/service/MobileAuthDeviceService.php new file mode 100644 index 0000000..03d1714 --- /dev/null +++ b/app/common/service/MobileAuthDeviceService.php @@ -0,0 +1,153 @@ +