mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-12 05:39:00 +08:00
fix(ImageCodeEndpoint): 修改验证码类型为动态参数,支持多种验证码类型
fix(ValidateCodeFilter): 更新验证码校验逻辑,支持滑块和点击文字验证码
This commit is contained in:
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));
|
||||
|
||||
+102
-101
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
+93
-88
@@ -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";
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user