tokenAuthService = $tokenAuthService; } /** * 用户登录 (返回Token) * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function login(Request $request) : JsonResponse { // 验证请求数据 $validator = Validator::make($request->all(), [ 'username' => ['required', 'string'], 'password' => ['required', 'string'], 'device_name' => ['string', 'nullable'] // 设备名称,用于Token标识 ], [ 'username.required' => '请输入用户名', 'password.required' => '请输入密码', ]); if ($validator->fails()) { return $this->Field($validator->errors()->first(), 422); } $credentials = $validator->validated(); // 手动验证用户 $user = User::where('username', $credentials['username']) ->where('status', 0) // 0表示正常状态,1表示停用 ->where('deleted', 0) // 确保用户未被删除 ->first(); if (!$user || !Hash::check($credentials['password'], $user->password)) { return $this->Field('用户名或密码错误,或账户已被停用', 401); } // 设备名称,默认为APP $deviceName = $credentials['device_name'] ?? 'APP-' . now()->format('Y-m-d H:i:s'); // 创建Token (删除该设备的旧Token,避免重复) $user->tokens()->where('name', $deviceName)->delete(); $token = $user->createToken($deviceName); // 更新最后登录信息 $user->update([ 'login_ip' => $request->ip(), 'login_date' => now(), ]); return $this->SuccessObject([ 'user' => [ 'id' => $user->id, 'username' => $user->username, 'nickname' => $user->nickname, 'email' => $user->email, 'mobile' => $user->mobile, 'avatar' => $user->avatar, 'dept_id' => $user->dept_id, ], 'token' => [ 'access_token' => $token->plainTextToken, 'token_type' => 'Bearer', 'expires_in' => null, // Sanctum默认不过期,可以在config/sanctum.php配置 ], 'message' => '登录成功' ]); } /** * APP登出 (删除当前Token) * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function logout(Request $request) : JsonResponse { $user = $request->user(); $currentToken = $request->bearerToken(); // 清空当前token的缓存 if ($currentToken) { $this->tokenAuthService->clearTokenCache($currentToken); } // 删除当前使用的token $user->currentAccessToken()->delete(); return $this->Success(['message' => '登出成功']); } /** * 登出所有设备 (删除用户所有Token) * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function logoutAll(Request $request) : JsonResponse { $user = $request->user(); // 清空用户所有token的缓存 $this->tokenAuthService->clearCacheOnLogout($user); // 删除用户的所有token $user->tokens()->delete(); return $this->Success(['message' => '已登出所有设备']); } /** * 清空认证缓存 * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function clearAuthCache(Request $request) : JsonResponse { $type = $request->input('type', 'current'); // current, user, all switch ($type) { case 'current': // 清空当前token缓存 $currentToken = $request->bearerToken(); if ($currentToken) { $result = $this->tokenAuthService->clearTokenCache($currentToken); return $this->Success([ 'message' => '当前token缓存清空成功', 'cleared' => $result ]); } return $this->Field('未找到当前token'); case 'user': // 清空当前用户所有token缓存 $user = $request->user(); $clearedCount = $this->tokenAuthService->clearCacheOnLogout($user); return $this->Success([ 'message' => '用户所有token缓存清空成功', 'cleared_count' => $clearedCount ]); case 'all': // 清空所有认证缓存(管理员功能) $result = $this->tokenAuthService->clearAllAuthCache(); return $this->Success([ 'message' => '所有认证缓存清空成功', 'success' => $result ]); default: return $this->Field('无效的缓存类型'); } } /** * 获取缓存统计信息 * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function getCacheStats(Request $request) : JsonResponse { $stats = $this->tokenAuthService->getCacheStats(); return $this->Success([ 'message' => '缓存统计信息', 'stats' => $stats ]); } /** * 获取当前用户信息 * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function me(Request $request) : JsonResponse { $user = $request->user(); return $this->Success([ 'id' => $user->id, 'username' => $user->username, 'nickname' => $user->nickname, 'email' => $user->email, 'mobile' => $user->mobile, 'avatar' => $user->avatar, 'dept_id' => $user->dept_id, 'login_date' => $user->login_date?->format('Y-m-d H:i:s'), 'login_ip' => $user->login_ip, 'current_token' => [ 'name' => $request->user()->currentAccessToken()->name, 'created_at' => $request->user()->currentAccessToken()->created_at->format('Y-m-d H:i:s'), 'last_used_at' => $request->user()->currentAccessToken()->last_used_at?->format('Y-m-d H:i:s'), ] ]); } /** * 刷新Token (删除旧Token,创建新Token) * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function refresh(Request $request) : JsonResponse { $user = $request->user(); $currentToken = $request->user()->currentAccessToken(); // 获取当前token的设备名 $deviceName = $currentToken->name; // 删除当前token $currentToken->delete(); // 创建新token $newToken = $user->createToken($deviceName); return $this->Success([ 'token' => [ 'access_token' => $newToken->plainTextToken, 'token_type' => 'Bearer', 'expires_in' => null, ], 'message' => 'Token刷新成功' ]); } /** * 获取用户所有设备/Token列表 * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function devices(Request $request) : JsonResponse { $tokens = $request->user()->tokens; $devices = $tokens->map(function ($token) { return [ 'id' => $token->id, 'name' => $token->name, 'created_at' => $token->created_at->format('Y-m-d H:i:s'), 'last_used_at' => $token->last_used_at?->format('Y-m-d H:i:s'), 'is_current' => $token->id === request()->user()->currentAccessToken()->id, ]; }); return $this->Success([ 'devices' => $devices, 'total' => $devices->count() ]); } /** * 删除指定设备/Token * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function deleteDevice(Request $request) : JsonResponse { $validator = Validator::make($request->all(), [ 'token_id' => ['required', 'integer', 'exists:personal_access_tokens,id'] ], [ 'token_id.required' => '请指定要删除的Token ID', 'token_id.exists' => 'Token不存在' ]); if ($validator->fails()) { return $this->Field($validator->errors()->first(), 422); } $tokenId = $request->token_id; $currentTokenId = $request->user()->currentAccessToken()->id; // 不能删除当前正在使用的token if ($tokenId == $currentTokenId) { return $this->Field('不能删除当前正在使用的设备', 400); } // 只能删除自己的token $deleted = $request->user()->tokens()->where('id', $tokenId)->delete(); if ($deleted) { return $this->Success(['message' => '设备删除成功']); } else { return $this->Field('设备删除失败', 500); } } }