From aa59dd79c1c92a77015b6078cbc76a25dedda3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Thu, 27 Mar 2025 15:28:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=99=BB=E5=BD=95=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/static/images/avatar.png | 2 +- Server/.env | 10 +- Server/application/common/controller/Auth.php | 22 ++- Server/application/common/model/User.php | 138 +++++++++--------- .../common/service/AuthService.php | 35 +++-- Server/application/common/validate/Auth.php | 23 ++- 6 files changed, 112 insertions(+), 118 deletions(-) diff --git a/Cunkebao/static/images/avatar.png b/Cunkebao/static/images/avatar.png index 0519ecba..b183cfa0 100644 --- a/Cunkebao/static/images/avatar.png +++ b/Cunkebao/static/images/avatar.png @@ -1 +1 @@ - \ No newline at end of file +data:image/png;base64,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 \ No newline at end of file diff --git a/Server/.env b/Server/.env index 9a16c12e..19693b28 100644 --- a/Server/.env +++ b/Server/.env @@ -4,11 +4,11 @@ trace = true [database] type = mysql -hostname = 103.144.2.26 -database = yi_54iis_com -username = yi_54iis_com -password = c1RbMwrZCCyxF1bC -hostport = 3306 +hostname = 56b4c23f6853c.gz.cdb.myqcloud.com +database = cunkebao_v3 +username = root +password = Zhiqun1984 +hostport = 14413 prefix = tk_ [api] diff --git a/Server/application/common/controller/Auth.php b/Server/application/common/controller/Auth.php index 3c73b5e1..b63ea9f7 100644 --- a/Server/application/common/controller/Auth.php +++ b/Server/application/common/controller/Auth.php @@ -53,8 +53,8 @@ class Auth extends Controller public function login() { // 获取登录参数 - $params = Request::only(['username', 'password', 'is_encrypted']); - + $params = Request::only(['account', 'password', 'typeId']); + // 参数验证 $validate = validate('common/Auth'); if (!$validate->scene('login')->check($params)) { @@ -62,16 +62,14 @@ class Auth extends Controller } try { - // 判断密码是否已加密 - $isEncrypted = isset($params['is_encrypted']) && $params['is_encrypted'] === true; - // 调用登录服务 $result = $this->authService->login( - $params['username'], + $params['account'], $params['password'], - Request::ip(), - $isEncrypted + $params['typeId'], + Request::ip() ); + return ResponseHelper::success($result, '登录成功'); } catch (\Exception $e) { return ResponseHelper::error($e->getMessage()); @@ -85,7 +83,7 @@ class Auth extends Controller public function mobileLogin() { // 获取登录参数 - $params = Request::only(['mobile', 'code', 'is_encrypted']); + $params = Request::only(['account', 'code', 'typeId']); // 参数验证 $validate = validate('common/Auth'); @@ -99,7 +97,7 @@ class Auth extends Controller // 调用手机号登录服务 $result = $this->authService->mobileLogin( - $params['mobile'], + $params['account'], $params['code'], Request::ip(), $isEncrypted @@ -118,7 +116,7 @@ class Auth extends Controller public function sendCode() { // 获取参数 - $params = Request::only(['mobile', 'type']); + $params = Request::only(['account', 'type']); // 参数验证 $validate = validate('common/Auth'); @@ -129,7 +127,7 @@ class Auth extends Controller try { // 调用发送验证码服务 $result = $this->authService->sendLoginCode( - $params['mobile'], + $params['account'], $params['type'] ); return ResponseHelper::success($result, '验证码发送成功'); diff --git a/Server/application/common/model/User.php b/Server/application/common/model/User.php index 769885fc..4deb182f 100644 --- a/Server/application/common/model/User.php +++ b/Server/application/common/model/User.php @@ -30,122 +30,108 @@ class User extends Model * 创建时间字段 * @var string */ - protected $createTime = 'create_at'; + protected $createTime = 'createTime'; /** * 更新时间字段 * @var string */ - protected $updateTime = 'update_at'; + protected $updateTime = 'updateTime'; /** * 软删除字段 * @var string */ - protected $deleteTime = 'delete_at'; + protected $deleteTime = 'deleteTime'; /** * 隐藏属性 * @var array */ - protected $hidden = ['password', 'delete_at']; + protected $hidden = ['passwordMd5', 'passwordLocal', 'deleteTime']; + + /** + * 字段类型 + * @var array + */ + protected $type = [ + 'id' => 'integer', + 'isAdmin' => 'integer', + 'companyId' => 'integer', + 'typeId' => 'integer', + 'lastLoginTime' => 'integer', + 'status' => 'integer', + 'createTime' => 'integer', + 'updateTime' => 'integer', + 'deleteTime' => 'integer' + ]; /** * 获取管理员用户信息 - * @param string $username 用户名 + * @param string $account 账号(手机号) * @param string $password 密码(可能是加密后的) - * @param bool $isEncrypted 密码是否已加密 + * @param int $typeId 身份信息 * @return array|null */ - public static function getAdminUser($username, $password, $isEncrypted = false) + public static function getAdminUser($account, $password, $typeId) { // 查询用户 - $user = self::where('username', $username)->find(); - + $user = self::where('account', $account) + ->where('typeId', $typeId) + ->where('status', 1) + ->find(); if (!$user) { // 记录日志 - \think\facade\Log::info('用户不存在', ['username' => $username]); + \think\facade\Log::info('用户不存在或已禁用', ['account' => $account]); return null; } // 记录密码验证信息 \think\facade\Log::info('密码验证', [ - 'username' => $username, + 'account' => $account, 'input_password' => $password, - 'stored_hash' => $user->password, - 'is_encrypted' => $isEncrypted, - 'password_info' => password_get_info($user->password) + 'stored_hash' => $user->passwordMd5, ]); // 验证密码 - $isValid = false; - - if ($isEncrypted) { - // 前端已加密,直接比较哈希值 - // 注意:这里需要确保前端和后端使用相同的加密算法和盐值 - $storedHash = self::getStoredHash($user->password); - $isValid = hash_equals($storedHash, $password); - - \think\facade\Log::info('加密密码验证', [ - 'username' => $username, - 'stored_hash' => $storedHash, - 'input_hash' => $password, - 'is_valid' => $isValid - ]); - } else { - // 未加密,使用password_verify验证 - $isValid = password_verify($password, $user->password); - } - + $isValid = password_verify($password, $user->passwordMd5); + \think\facade\Log::info('密码验证结果', [ - 'username' => $username, + 'account' => $account, 'is_valid' => $isValid, - 'is_encrypted' => $isEncrypted ]); if (!$isValid) { return null; } + // 更新登录信息 + $user->lastLoginIp = request()->ip(); + $user->lastLoginTime = time(); + $user->save(); + return [ 'id' => $user->id, - 'username' => $user->username, - 'name' => $user->username, // 暂时使用username作为name - 'role' => 'admin', // 暂时固定为admin角色 - 'permissions' => ['*'], // 暂时拥有所有权限 + 'account' => $user->account, + 'isAdmin' => $user->isAdmin, + 'companyId' => $user->companyId, + 'typeId' => $user->typeId, + 'lastLoginIp' => $user->lastLoginIp, + 'lastLoginTime' => $user->lastLoginTime ]; } - /** - * 获取存储的哈希值 - * 用于前端加密密码的验证 - * @param string $bcryptHash 数据库中存储的bcrypt哈希值 - * @return string 用于前端验证的哈希值 - */ - protected static function getStoredHash($bcryptHash) - { - // 这里需要实现与前端相同的加密算法 - // 例如,如果前端使用SHA256加盐,这里需要提取原始密码并进行相同的处理 - // 注意:这只是一个示例,实际实现可能需要根据您的具体需求调整 - - // 假设我们能够从bcrypt哈希中提取原始密码(实际上这是不可能的,这里只是示例) - // 在实际应用中,您需要在用户注册或修改密码时同时存储前端加密的哈希值 - $originalPassword = '123456'; // 这里应该是从数据库中获取的原始密码 - $salt = 'yishi_salt_2024'; // 与前端相同的盐值 - - // 使用与前端相同的算法 - return hash('sha256', $originalPassword . $salt); - } - /** * 通过手机号获取用户信息 - * @param string $mobile 手机号 + * @param string $account 手机号 * @return array|null */ - public static function getUserByMobile($mobile) + public static function getUserByMobile($account) { // 查询用户 - $user = self::where('mobile', $mobile)->find(); + $user = self::where('account', $account) + ->where('status', 1) + ->find(); if (!$user) { return null; @@ -153,11 +139,27 @@ class User extends Model return [ 'id' => $user->id, - 'username' => $user->username, - 'name' => $user->username, // 暂时使用username作为name - 'mobile' => $user->mobile, - 'role' => 'user', // 暂时固定为user角色 - 'permissions' => ['user'], // 暂时拥有用户权限 + 'account' => $user->account, + 'isAdmin' => $user->isAdmin, + 'companyId' => $user->companyId, + 'typeId' => $user->typeId, + 'role' => $user->isAdmin ? 'admin' : 'user', + 'permissions' => $user->isAdmin ? ['*'] : ['user'] ]; } + + /** + * 验证用户密码 + * @param string $password 密码 + * @param bool $isEncrypted 是否已加密 + * @return bool + */ + public function verifyPassword($password, $isEncrypted = false) + { + if ($isEncrypted) { + return hash_equals($this->passwordMd5, $password); + } else { + return $this->passwordMd5 === md5($password); + } + } } \ No newline at end of file diff --git a/Server/application/common/service/AuthService.php b/Server/application/common/service/AuthService.php index 32abbf0a..b18ba5c4 100644 --- a/Server/application/common/service/AuthService.php +++ b/Server/application/common/service/AuthService.php @@ -31,22 +31,21 @@ class AuthService /** * 用户登录 - * @param string $username 用户名 + * @param string $account 账号(手机号) * @param string $password 密码(可能是加密后的) * @param string $ip 登录IP - * @param bool $isEncrypted 密码是否已加密 * @return array * @throws \Exception */ - public function login($username, $password, $ip, $isEncrypted = false) + public function login($account, $password, $typeId, $ip) { // 获取用户信息 - $user = User::getAdminUser($username, $password, $isEncrypted); - + $user = User::getAdminUser($account, $password, $typeId); + if (empty($user)) { // 记录登录失败 - Log::info('登录失败', ['username' => $username, 'ip' => $ip, 'is_encrypted' => $isEncrypted]); - throw new \Exception('用户名或密码错误'); + Log::info('登录失败', ['account' => $account, 'ip' => $ip, 'is_encrypted' => true]); + throw new \Exception('账号或密码错误'); } // 生成JWT令牌 @@ -54,7 +53,7 @@ class AuthService $expireTime = time() + self::TOKEN_EXPIRE; // 记录登录成功 - Log::info('登录成功', ['username' => $username, 'ip' => $ip]); + Log::info('登录成功', ['account' => $account, 'ip' => $ip]); return [ 'token' => $token, @@ -65,25 +64,25 @@ class AuthService /** * 手机号验证码登录 - * @param string $mobile 手机号 + * @param string $account 手机号 * @param string $code 验证码(可能是加密后的) * @param string $ip 登录IP * @param bool $isEncrypted 验证码是否已加密 * @return array * @throws \Exception */ - public function mobileLogin($mobile, $code, $ip, $isEncrypted = false) + public function mobileLogin($account, $code, $ip, $isEncrypted = false) { // 验证验证码 - if (!$this->smsService->verifyCode($mobile, $code, 'login', $isEncrypted)) { - Log::info('验证码验证失败', ['mobile' => $mobile, 'ip' => $ip, 'is_encrypted' => $isEncrypted]); + if (!$this->smsService->verifyCode($account, $code, 'login', $isEncrypted)) { + Log::info('验证码验证失败', ['account' => $account, 'ip' => $ip, 'is_encrypted' => $isEncrypted]); throw new \Exception('验证码错误或已过期'); } // 获取用户信息 - $user = User::getUserByMobile($mobile); + $user = User::getUserByMobile($account); if (empty($user)) { - Log::info('用户不存在', ['mobile' => $mobile, 'ip' => $ip]); + Log::info('用户不存在', ['account' => $account, 'ip' => $ip]); throw new \Exception('用户不存在'); } @@ -92,7 +91,7 @@ class AuthService $expireTime = time() + self::TOKEN_EXPIRE; // 记录登录成功 - Log::info('手机号登录成功', ['mobile' => $mobile, 'ip' => $ip]); + Log::info('手机号登录成功', ['account' => $account, 'ip' => $ip]); return [ 'token' => $token, @@ -103,14 +102,14 @@ class AuthService /** * 发送登录验证码 - * @param string $mobile 手机号 + * @param string $account 手机号 * @param string $type 验证码类型 * @return array * @throws \Exception */ - public function sendLoginCode($mobile, $type) + public function sendLoginCode($account, $type) { - return $this->smsService->sendCode($mobile, $type); + return $this->smsService->sendCode($account, $type); } /** diff --git a/Server/application/common/validate/Auth.php b/Server/application/common/validate/Auth.php index d5507360..ca89a4d0 100644 --- a/Server/application/common/validate/Auth.php +++ b/Server/application/common/validate/Auth.php @@ -13,12 +13,10 @@ class Auth extends Validate * @var array */ protected $rule = [ - 'username' => 'require|length:3,20', + 'account' => 'require|mobile', 'password' => 'require|length:6,64', - 'mobile' => 'require|mobile', 'code' => 'require|length:4,6', - 'is_encrypted' => 'boolean', - 'type' => 'require|in:login,register', + 'typeId' => 'require|in:1,2', ]; /** @@ -26,17 +24,14 @@ class Auth extends Validate * @var array */ protected $message = [ - 'username.require' => '用户名不能为空', - 'username.length' => '用户名长度必须在3-20个字符之间', + 'account.require' => '账号不能为空', + 'account.mobile' => '账号格式不正确(需要是手机号)', 'password.require' => '密码不能为空', 'password.length' => '密码长度必须在6-64个字符之间', - 'mobile.require' => '手机号不能为空', - 'mobile.mobile' => '手机号格式不正确', 'code.require' => '验证码不能为空', 'code.length' => '验证码长度必须在4-6个字符之间', - 'is_encrypted.boolean' => '加密标志必须为布尔值', - 'type.require' => '验证码类型不能为空', - 'type.in' => '验证码类型不正确', + 'typeId.require' => '用户类型不能为空', + 'typeId.in' => '用户类型错误', ]; /** @@ -44,9 +39,9 @@ class Auth extends Validate * @var array */ protected $scene = [ - 'login' => ['username', 'password', 'is_encrypted'], - 'mobile_login' => ['mobile', 'code', 'is_encrypted'], + 'login' => ['account', 'password', 'typeId'], + 'mobile_login' => ['account', 'code', 'typeId'], 'refresh' => [], - 'send_code' => ['mobile', 'type'], + 'send_code' => ['account', 'type'], ]; } \ No newline at end of file