fix(ImageCodeEndpoint): 修改验证码类型为动态参数,支持多种验证码类型

fix(ValidateCodeFilter): 更新验证码校验逻辑,支持滑块和点击文字验证码
This commit is contained in:
PIGCLOUD committed 2025-11-18 09:39:37 +08:00
1 parent 1a8d0c0898
commit 6d837c6f1c
3 files changed
+198 -193

No files matched your search

@@ -4,7 +4,6 @@ import cn.hutool.core.lang.Validator;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
@@ -59,9 +58,9 @@ public class ImageCodeEndpoint {
*/
@SneakyThrows
@GetMapping("/create")
public R behavior() {
public R behavior(String captchaType) {
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
vo.setCaptchaType(captchaType);
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
return R.ok(captchaService.get(vo));
}
@@ -75,7 +74,7 @@ public class ImageCodeEndpoint {
CaptchaVO vo = new CaptchaVO();
vo.setPointJson(request.getParameter("pointJson"));
vo.setToken(request.getParameter("token"));
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
vo.setCaptchaType(request.getParameter("captchaType"));
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
return R.ok(captchaService.check(vo));
@@ -45,129 +45,130 @@ import java.io.IOException;
@RequiredArgsConstructor
public class ValidateCodeFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String requestUrl = request.getServletPath();
String requestUrl = request.getServletPath();
// 不是登录URL 请求直接跳过
if (!SecurityConstants.OAUTH_TOKEN_URL.equals(requestUrl)) {
filterChain.doFilter(request, response);
return;
}
// 不是登录URL 请求直接跳过
if (!SecurityConstants.OAUTH_TOKEN_URL.equals(requestUrl)) {
filterChain.doFilter(request, response);
return;
}
// 如果登录URL 但是刷新token的请求,直接向下执行
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (StrUtil.containsAny(grantType, SecurityConstants.REFRESH_TOKEN)) {
filterChain.doFilter(request, response);
return;
}
// 如果登录URL 但是刷新token的请求,直接向下执行
String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
if (StrUtil.containsAny(grantType, SecurityConstants.REFRESH_TOKEN)) {
filterChain.doFilter(request, response);
return;
}
// mobile模式, 如果请求不包含mobile 参数直接
String mobile = request.getParameter(SecurityConstants.GRANT_MOBILE);
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) {
throw new OAuth2AuthenticationException(SecurityConstants.GRANT_MOBILE);
}
// mobile模式, 如果请求不包含mobile 参数直接
String mobile = request.getParameter(SecurityConstants.GRANT_MOBILE);
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) {
throw new OAuth2AuthenticationException(SecurityConstants.GRANT_MOBILE);
}
// mobile模式, 社交登录模式不校验验证码直接跳过
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) {
filterChain.doFilter(request, response);
return;
}
// mobile模式, 社交登录模式不校验验证码直接跳过
if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) {
filterChain.doFilter(request, response);
return;
}
// 判断客户端是否跳过检验
if (!isCheckCaptchaClient(request)) {
filterChain.doFilter(request, response);
return;
}
// 判断客户端是否跳过检验
if (!isCheckCaptchaClient(request)) {
filterChain.doFilter(request, response);
return;
}
// 校验验证码 1. 客户端开启验证码 2. 短信模式
try {
checkCode();
filterChain.doFilter(request, response);
// 校验验证码 1. 客户端开启验证码 2. 短信模式
try {
checkCode();
filterChain.doFilter(request, response);
} catch (ValidateCodeException validateCodeException) {
throw new OAuth2AuthenticationException(validateCodeException.getMessage());
}
}
throw new OAuth2AuthenticationException(validateCodeException.getMessage());
}
}
/**
* 校验验证码
*/
private void checkCode() throws ValidateCodeException {
HttpServletRequest request = WebUtils.getRequest();
String code = request.getParameter("code");
/**
* 校验验证码
*/
private void checkCode() throws ValidateCodeException {
HttpServletRequest request = WebUtils.getRequest();
String code = request.getParameter("code");
if (StrUtil.isBlank(code)) {
throw new ValidateCodeException("验证码不能为空");
}
if (StrUtil.isBlank(code)) {
throw new ValidateCodeException("验证码不能为空");
}
String randomStr = request.getParameter("randomStr");
String randomStr = request.getParameter("randomStr");
// https://gitee.com/log4j/pig/issues/IWA0D
String mobile = request.getParameter("mobile");
if (StrUtil.isNotBlank(mobile)) {
randomStr = mobile;
}
// https://gitee.com/log4j/pig/issues/IWA0D
String mobile = request.getParameter("mobile");
if (StrUtil.isNotBlank(mobile)) {
randomStr = mobile;
}
// 若是滑块登录
if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) {
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaVerification(code);
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
if (!captchaService.verification(vo).isSuccess()) {
throw new ValidateCodeException("验证码不能为空");
}
return;
}
// 若是滑块登录
if (StrUtil.equalsAnyIgnoreCase(randomStr, CommonConstants.IMAGE_CODE_BLOCK_PUZZLE, CommonConstants.IMAGE_CODE_CLICK_WORD)) {
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaVerification(code);
vo.setCaptchaType(randomStr);
if (!captchaService.verification(vo).isSuccess()) {
throw new ValidateCodeException("验证码不能为空");
}
return;
}
String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
if (!RedisUtils.hasKey(key)) {
throw new ValidateCodeException("验证码不合法");
}
String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
if (!RedisUtils.hasKey(key)) {
throw new ValidateCodeException("验证码不合法");
}
String codeObj = RedisUtils.get(key);
String codeObj = RedisUtils.get(key);
if (codeObj == null) {
throw new ValidateCodeException("验证码不合法");
}
if (codeObj == null) {
throw new ValidateCodeException("验证码不合法");
}
if (StrUtil.isBlank(codeObj)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
if (StrUtil.isBlank(codeObj)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
if (!StrUtil.equals(codeObj, code)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
if (!StrUtil.equals(codeObj, code)) {
RedisUtils.delete(key);
throw new ValidateCodeException("验证码不合法");
}
RedisUtils.delete(key);
}
RedisUtils.delete(key);
}
/**
* 是否需要校验客户端,根据client 查询客户端配置
* @param request 请求
* @return true 需要校验, false 不需要校验
*/
private boolean isCheckCaptchaClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
/**
* 是否需要校验客户端,根据client 查询客户端配置
*
* @param request 请求
* @return true 需要校验, false 不需要校验
*/
private boolean isCheckCaptchaClient(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
String clientId = WebUtils.extractClientId(header).orElse(null);
// 获取租户拼接区分租户的key
String tenantId = request.getHeader(CommonConstants.TENANT_ID);
String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId,
CacheConstants.CLIENT_FLAG, clientId);
String val = RedisUtils.get(key);
String val = RedisUtils.get(key);
// 当配置不存在时,不用校验
if (val == null) {
return false;
}
// 当配置不存在时,不用校验
if (val == null) {
return false;
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG));
}
JSONObject information = JSONUtil.parseObj(val);
return !StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG));
}
}
@@ -25,114 +25,119 @@ package com.pig4cloud.pigx.common.core.constant;
*/
public interface CommonConstants {
/**
* header 中租户ID
*/
String TENANT_ID = "TENANT-ID";
/**
* header 中租户ID
*/
String TENANT_ID = "TENANT-ID";
/**
* header 中版本信息
*/
String VERSION = "VERSION";
/**
* header 中版本信息
*/
String VERSION = "VERSION";
/**
* 租户ID
*/
Long TENANT_ID_1 = 1L;
/**
* 租户ID
*/
Long TENANT_ID_1 = 1L;
/**
* 删除
*/
String STATUS_DEL = "1";
/**
* 删除
*/
String STATUS_DEL = "1";
/**
* 正常
*/
String STATUS_NORMAL = "0";
/**
* 正常
*/
String STATUS_NORMAL = "0";
/**
* 锁定
*/
String STATUS_LOCK = "9";
/**
* 锁定
*/
String STATUS_LOCK = "9";
/**
* 菜单树根节点
*/
Long MENU_TREE_ROOT_ID = -1L;
/**
* 菜单树根节点
*/
Long MENU_TREE_ROOT_ID = -1L;
/**
* 编码
*/
String UTF8 = "UTF-8";
/**
* 编码
*/
String UTF8 = "UTF-8";
/**
* 前端工程名
*/
String FRONT_END_PROJECT = "pigx-ui";
/**
* 前端工程名
*/
String FRONT_END_PROJECT = "pigx-ui";
/**
* 移动端工程名
*/
String UNI_END_PROJECT = "pigx-app";
/**
* 移动端工程名
*/
String UNI_END_PROJECT = "pigx-app";
/**
* 后端工程名
*/
String BACK_END_PROJECT = "pigx";
/**
* 后端工程名
*/
String BACK_END_PROJECT = "pigx";
/**
* 公共参数
*/
String PIG_PUBLIC_PARAM_KEY = "PIG_PUBLIC_PARAM_KEY";
/**
* 公共参数
*/
String PIG_PUBLIC_PARAM_KEY = "PIG_PUBLIC_PARAM_KEY";
/**
* 成功标记
*/
Integer SUCCESS = 0;
/**
* 成功标记
*/
Integer SUCCESS = 0;
/**
* 失败标记
*/
Integer FAIL = 1;
/**
* 失败标记
*/
Integer FAIL = 1;
/**
* 默认存储bucket
*/
String BUCKET_NAME = "lengleng";
/**
* 默认存储bucket
*/
String BUCKET_NAME = "lengleng";
/**
* 滑块验证码
*/
String IMAGE_CODE_TYPE = "blockPuzzle";
/**
* 滑块验证码
*/
String IMAGE_CODE_BLOCK_PUZZLE = "blockPuzzle";
/**
* 验证码开关
*/
String CAPTCHA_FLAG = "captcha_flag";
/**
* 点击文字验证码类型
*/
String IMAGE_CODE_CLICK_WORD = "clickWord";
/**
* 密码传输是否加密
*/
String ENC_FLAG = "enc_flag";
/**
* 验证码开关
*/
String CAPTCHA_FLAG = "captcha_flag";
/**
* 客户端允许同时在线数量
*/
String ONLINE_QUANTITY = "online_quantity";
/**
* 密码传输是否加密
*/
String ENC_FLAG = "enc_flag";
/**
* 请求开始时间
*/
String REQUEST_START_TIME = "REQUEST-START-TIME";
/**
* 客户端允许同时在线数量
*/
String ONLINE_QUANTITY = "online_quantity";
/**
* 当前页
*/
String CURRENT = "current";
/**
* 请求开始时间
*/
String REQUEST_START_TIME = "REQUEST-START-TIME";
/**
* size
*/
String SIZE = "size";
/**
* 当前页
*/
String CURRENT = "current";
/**
* size
*/
String SIZE = "size";
}