diff --git a/app/api/controller/User.php b/app/api/controller/User.php index 117b08a5..8ebdfeac 100644 --- a/app/api/controller/User.php +++ b/app/api/controller/User.php @@ -39,6 +39,8 @@ class User extends Frontend ], $this->auth::LOGIN_RESPONSE_CODE); } + $userLoginCaptchaSwitch = Config::get('buildadmin.user_login_captcha'); + if ($this->request->isPost()) { $params = $this->request->post(['tab', 'email', 'mobile', 'username', 'password', 'keep', 'captcha', 'captchaId', 'captchaInfo', 'registerType']); if (!in_array($params['tab'], ['login', 'register'])) { @@ -53,9 +55,11 @@ class User extends Frontend } if ($params['tab'] == 'login') { - $captchaObj = new ClickCaptcha(); - if (!$captchaObj->check($params['captchaId'], $params['captchaInfo'])) { - $this->error(__('Captcha error')); + if ($userLoginCaptchaSwitch) { + $captchaObj = new ClickCaptcha(); + if (!$captchaObj->check($params['captchaId'], $params['captchaInfo'])) { + $this->error(__('Captcha error')); + } } $res = $this->auth->login($params['username'], $params['password'], (bool)$params['keep']); } elseif ($params['tab'] == 'register') { @@ -79,6 +83,7 @@ class User extends Frontend } $this->success('', [ + 'userLoginCaptchaSwitch' => $userLoginCaptchaSwitch, 'accountVerificationType' => get_account_verification_type() ]); } diff --git a/app/api/validate/User.php b/app/api/validate/User.php index 4cac86cb..9dc310b3 100644 --- a/app/api/validate/User.php +++ b/app/api/validate/User.php @@ -3,6 +3,7 @@ namespace app\api\validate; use think\Validate; +use think\facade\Config; class User extends Validate { @@ -13,7 +14,9 @@ class User extends Validate 'email' => 'email|unique:user', 'mobile' => 'mobile|unique:user', 'password' => 'require|regex:^(?!.*[&<>"\'\n\r]).{6,32}$', + // 注册邮箱或手机验证码 'captcha' => 'require', + // 登录点选验证码 'captchaId' => 'require', 'captchaInfo' => 'require', ]; @@ -22,10 +25,26 @@ class User extends Validate * 验证场景 */ protected $scene = [ - 'login' => ['password', 'captchaId', 'captchaInfo'], - 'register' => ['email', 'username', 'password', 'mobile', 'captcha'], + 'register' => ['username', 'password', 'email', 'mobile', 'captcha'], ]; + /** + * 登录验证场景 + */ + public function sceneLogin(): User + { + $fields = ['username', 'password']; + + // 根据系统配置的登录验证码开关调整验证场景的字段 + $userLoginCaptchaSwitch = Config::get('buildadmin.user_login_captcha'); + if ($userLoginCaptchaSwitch) { + $fields[] = 'captchaId'; + $fields[] = 'captchaInfo'; + } + + return $this->only($fields)->remove('username', ['regex', 'unique']); + } + public function __construct() { $this->field = [ diff --git a/config/buildadmin.php b/config/buildadmin.php index 099f2a7d..12795473 100644 --- a/config/buildadmin.php +++ b/config/buildadmin.php @@ -6,6 +6,8 @@ return [ // 允许跨域访问的域名 'cors_request_domain' => 'localhost,127.0.0.1', + // 是否开启会员登录验证码 + 'user_login_captcha' => true, // 是否开启管理员登录验证码 'admin_login_captcha' => true, // 会员登录失败可重试次数,false则无限 diff --git a/web/src/views/frontend/user/login.vue b/web/src/views/frontend/user/login.vue index dfae3fb7..56bf803f 100644 --- a/web/src/views/frontend/user/login.vue +++ b/web/src/views/frontend/user/login.vue @@ -316,6 +316,7 @@ interface State { password: string } dialogWidth: number + userLoginCaptchaSwitch: boolean accountVerificationType: string[] codeSendCountdown: number submitRetrieveLoading: boolean @@ -345,6 +346,7 @@ const state: State = reactive({ password: '', }, dialogWidth: 36, + userLoginCaptchaSwitch: true, accountVerificationType: [], codeSendCountdown: 0, submitRetrieveLoading: false, @@ -398,7 +400,7 @@ const resize = () => { const onSubmitPre = () => { formRef.value?.validate((valid) => { if (!valid) return - if (state.form.tab == 'login') { + if (state.form.tab == 'login' && state.userLoginCaptchaSwitch) { clickCaptcha(state.form.captchaId, (captchaInfo: string) => onSubmit(captchaInfo)) } else { onSubmit() @@ -510,6 +512,7 @@ onMounted(async () => { useEventListener(window, 'resize', resize) checkIn('get').then((res) => { + state.userLoginCaptchaSwitch = res.data.userLoginCaptchaSwitch state.accountVerificationType = res.data.accountVerificationType state.retrievePasswordForm.type = res.data.accountVerificationType.length > 0 ? res.data.accountVerificationType[0] : '' })