新增登录页图形验证码功能,支持通过Redis全局配置控制验证码的启用状态,优化登录流程以提升用户体验。新增相关API接口和前端配置项,确保验证码逻辑与后端同步。
This commit is contained in:
@@ -12,6 +12,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
@@ -737,6 +738,46 @@ public class LoginController {
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录页是否启用图形验证码(未登录可访问)。优先 Redis 全局配置(与侧边栏项目配置同步),否则沿用 jeecg.firewall.enable-login-captcha
|
||||
*/
|
||||
@IgnoreAuth
|
||||
@GetMapping("/loginCaptchaConfig")
|
||||
@Operation(summary = "登录页是否启用图形验证码")
|
||||
public Result<Boolean> loginCaptchaConfig() {
|
||||
return Result.OK(isLoginCaptchaRequired());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存登录页图形验证码开关(写入 Redis,全站生效;需权限 system:project:setting:loginCaptcha)
|
||||
*/
|
||||
@PostMapping("/setLoginCaptchaConfig")
|
||||
@Operation(summary = "保存登录页图形验证码开关")
|
||||
@RequiresPermissions("system:project:setting:loginCaptcha")
|
||||
public Result<String> setLoginCaptchaConfig(@RequestBody JSONObject body) {
|
||||
Boolean enabled = body.getBoolean("enabled");
|
||||
if (enabled == null) {
|
||||
return Result.error("参数 enabled 不能为空");
|
||||
}
|
||||
redisUtil.set(CommonConstant.SYS_LOGIN_CAPTCHA_ENABLED, enabled.toString());
|
||||
baseCommonService.addLog("保存登录验证码开关: " + enabled, CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_3);
|
||||
return Result.OK("保存成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要在登录时校验图形验证码(Redis 覆盖 > firewall 配置)
|
||||
*/
|
||||
private boolean isLoginCaptchaRequired() {
|
||||
Object v = redisUtil.get(CommonConstant.SYS_LOGIN_CAPTCHA_ENABLED);
|
||||
if (v != null) {
|
||||
return Boolean.parseBoolean(v.toString());
|
||||
}
|
||||
return jeecgBaseConfig.getFirewall() == null
|
||||
|| jeecgBaseConfig.getFirewall().getEnableLoginCaptcha() == null
|
||||
|| Boolean.TRUE.equals(jeecgBaseConfig.getFirewall().getEnableLoginCaptcha());
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录二维码
|
||||
*/
|
||||
@@ -917,9 +958,9 @@ public class LoginController {
|
||||
* 校验验证码工具方法,校验失败直接返回Result,校验通过返回realKey
|
||||
*/
|
||||
private String validateCaptcha(SysLoginModel sysLoginModel, Result<JSONObject> result) {
|
||||
// 判断是否启用登录验证码校验
|
||||
if (jeecgBaseConfig.getFirewall() != null && Boolean.FALSE.equals(jeecgBaseConfig.getFirewall().getEnableLoginCaptcha())) {
|
||||
log.warn("关闭了登录验证码校验,跳过验证码校验!");
|
||||
// 是否启用登录验证码(含 Redis 全局开关与 firewall 配置)
|
||||
if (!isLoginCaptchaRequired()) {
|
||||
log.warn("已关闭登录验证码校验(Redis 全局或 firewall),跳过验证码校验!");
|
||||
return "LoginWithoutVerifyCode";
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ public class SysCheckRuleServiceImpl extends ServiceImpl<SysCheckRuleMapper, Sys
|
||||
for (int i = 0; i < rules.size(); i++) {
|
||||
JSONObject result = new JSONObject();
|
||||
JSONObject rule = rules.getJSONObject(i);
|
||||
// 全局规则可选「不执行」:priority 为 2 时跳过本条(仅保留配置,不参与校验)
|
||||
String priority = rule.getString("priority");
|
||||
if ("2".equals(priority)) {
|
||||
continue;
|
||||
}
|
||||
// 位数
|
||||
String digits = rule.getString("digits");
|
||||
result.put("digits", digits);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 编码校验规则:系统登录密码(规则编码 sys_login_password)
|
||||
-- 全局规则拆成多条:长度 → 字母 → 数字 → 特殊字符,按顺序校验,先失败先提示
|
||||
DELETE FROM sys_check_rule WHERE rule_code = 'sys_login_password';
|
||||
|
||||
INSERT INTO sys_check_rule (
|
||||
id,
|
||||
rule_name,
|
||||
rule_code,
|
||||
rule_json,
|
||||
rule_description,
|
||||
create_by,
|
||||
create_time
|
||||
) VALUES (
|
||||
'1990000000000000001',
|
||||
'系统登录密码',
|
||||
'sys_login_password',
|
||||
CONVERT(UNHEX('5b7b22646967697473223a222a222c227061747465726e223a225e2e7b382c7d24222c226d657373616765223a22e5af86e7a081e995bfe5baa6e887b3e5b091e4b8ba203820e4bd8d222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5b612d7a412d5a5d292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe5ad97e6af8d222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5c5c64292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe695b0e5ad97222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5b7e21402324255e262a28295f2b5c5c2d3d7b7d5c5c5b5c5c5d3a3b5c225c5c75303032373c3e3f2c2e2f5d292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe789b9e6ae8ae5ad97e7aca6efbc88e5a682207e214023242520e7ad89efbc89222c227072696f72697479223a2231227d5d') USING utf8mb4),
|
||||
'供用户管理、修改密码等调用;全局规则共 4 条(长度/字母/数字/特殊字符),与前端 utils/sys/sysPasswordRules 约定规则编码 sys_login_password。',
|
||||
'admin',
|
||||
NOW()
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
-- 已部署环境若已执行过 V3.9.2_1:将单条正则升级为「多条全局规则」拆分(与 V3.9.2_1 最终内容一致,可重复执行)
|
||||
DELETE FROM sys_check_rule WHERE rule_code = 'sys_login_password';
|
||||
|
||||
INSERT INTO sys_check_rule (
|
||||
id,
|
||||
rule_name,
|
||||
rule_code,
|
||||
rule_json,
|
||||
rule_description,
|
||||
create_by,
|
||||
create_time
|
||||
) VALUES (
|
||||
'1990000000000000001',
|
||||
'系统登录密码',
|
||||
'sys_login_password',
|
||||
CONVERT(UNHEX('5b7b22646967697473223a222a222c227061747465726e223a225e2e7b382c7d24222c226d657373616765223a22e5af86e7a081e995bfe5baa6e887b3e5b091e4b8ba203820e4bd8d222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5b612d7a412d5a5d292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe5ad97e6af8d222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5c5c64292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe695b0e5ad97222c227072696f72697479223a2231227d2c7b22646967697473223a222a222c227061747465726e223a225e283f3d2e2a5b7e21402324255e262a28295f2b5c5c2d3d7b7d5c5c5b5c5c5d3a3b5c225c5c75303032373c3e3f2c2e2f5d292e2a24222c226d657373616765223a22e5af86e7a081e5bf85e9a1bbe58c85e590abe789b9e6ae8ae5ad97e7aca6efbc88e5a682207e214023242520e7ad89efbc89222c227072696f72697479223a2231227d5d') USING utf8mb4),
|
||||
'供用户管理、修改密码等调用;全局规则共 4 条(长度/字母/数字/特殊字符),与前端 utils/sys/sysPasswordRules 约定规则编码 sys_login_password。',
|
||||
'admin',
|
||||
NOW()
|
||||
);
|
||||
@@ -0,0 +1,5 @@
|
||||
-- 项目配置抽屉「验证码登录」开关的按钮权限(授权后可在界面设置中看到该开关)
|
||||
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('2000210000000000001', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '项目配置-验证码登录开关', NULL, NULL, 0, NULL, NULL, 2, 'system:project:setting:loginCaptcha', '1', 99.00, 0, NULL, 1, 0, 0, 0, '控制项目配置抽屉中「验证码登录」开关是否展示', 'admin', NOW(), NULL, NULL, 0, 0, '1', 0);
|
||||
|
||||
-- 默认授权给管理员角色(与历史脚本中 admin 角色 id 一致)
|
||||
INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) VALUES ('2000210000000000002', 'f6817f48af4fb3af11b9e8bf182f618b', '2000210000000000001', NULL, NOW(), '127.0.0.1');
|
||||
Reference in New Issue
Block a user