mirror of https://gitee.com/stylefeng/roses
【validator-sdk-captcha】图形验证码模块【CaptchaController】图形验证码接口
parent
504aa0d1ed
commit
ea0bc554ca
|
@ -57,6 +57,13 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- EasyCaptcha图形验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -34,8 +34,12 @@ public class LoginRequest extends BaseRequest {
|
|||
private Boolean rememberMe = false;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
* 图形验证码
|
||||
*/
|
||||
private String kaptcha;
|
||||
private String verCode;
|
||||
|
||||
/**
|
||||
* 缓存 key
|
||||
*/
|
||||
private String verKey;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package cn.stylefeng.roses.kernel.auth.auth;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.stylefeng.roses.kernel.auth.api.AuthServiceApi;
|
||||
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
|
||||
import cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants;
|
||||
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
|
||||
import cn.stylefeng.roses.kernel.auth.api.exception.AuthException;
|
||||
import cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum;
|
||||
|
@ -23,6 +22,7 @@ import cn.stylefeng.roses.kernel.system.UserServiceApi;
|
|||
import cn.stylefeng.roses.kernel.system.enums.UserStatusEnum;
|
||||
import cn.stylefeng.roses.kernel.system.expander.SystemConfigExpander;
|
||||
import cn.stylefeng.roses.kernel.system.pojo.user.UserLoginInfoDTO;
|
||||
import cn.stylefeng.roses.kernel.validator.CaptchaApi;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -60,6 +60,9 @@ public class AuthServiceImpl implements AuthServiceApi {
|
|||
@Resource
|
||||
private LoginLogServiceApi loginLogServiceApi;
|
||||
|
||||
@Resource
|
||||
private CaptchaApi captchaApi;
|
||||
|
||||
@Override
|
||||
public LoginResponse login(LoginRequest loginRequest) {
|
||||
return loginAction(loginRequest, true);
|
||||
|
@ -169,13 +172,12 @@ public class AuthServiceImpl implements AuthServiceApi {
|
|||
|
||||
// 2. 如果开启了验证码校验,则验证当前请求的验证码是否正确
|
||||
if (SystemConfigExpander.getCaptchaOpen()) {
|
||||
|
||||
String kaptcha = loginRequest.getKaptcha();
|
||||
if (StrUtil.isEmpty(kaptcha)) {
|
||||
String verCode = loginRequest.getVerCode();
|
||||
String verKey = loginRequest.getVerKey();
|
||||
if (StrUtil.isEmpty(verCode) || StrUtil.isEmpty(verKey)) {
|
||||
throw new AuthException(AuthExceptionEnum.KAPTCHA_EMPTY);
|
||||
}
|
||||
Object sessionKaptcha = (String) HttpServletUtil.getRequest().getSession().getAttribute(AuthConstants.KAPTCHA_SESSION_KEY);
|
||||
if (StrUtil.isEmpty(kaptcha) || !kaptcha.equals(sessionKaptcha)) {
|
||||
if (!captchaApi.validate(verCode, verKey)) {
|
||||
throw new AuthException(AuthExceptionEnum.KAPTCHA_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<module>validator-sdk-black-white</module>
|
||||
<module>validator-sdk-xss</module>
|
||||
<module>validator-business-count</module>
|
||||
<module>validator-sdk-captcha</module>
|
||||
<module>validator-spring-boot-starter</module>
|
||||
</modules>
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package cn.stylefeng.roses.kernel.validator;
|
||||
|
||||
import cn.stylefeng.roses.kernel.validator.pojo.EasyCaptcha;
|
||||
|
||||
/**
|
||||
* 图形验证码Api
|
||||
* <p>
|
||||
* 开启用户登录图形验证码后获取图形验证码
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:46
|
||||
*/
|
||||
public interface CaptchaApi {
|
||||
|
||||
/**
|
||||
* 生成图形验证码
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 12:38
|
||||
*/
|
||||
EasyCaptcha captcha();
|
||||
|
||||
/**
|
||||
* 校验图形验证码
|
||||
*
|
||||
* @param verCode 验证码
|
||||
* @param verKey 缓存key值
|
||||
* @return
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 12:38
|
||||
*/
|
||||
boolean validate(String verCode, String verKey);
|
||||
|
||||
/**
|
||||
* 根据key值获取验证码
|
||||
*
|
||||
* @param verKey 缓存key值
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 12:40
|
||||
*/
|
||||
String getVerCode(String verKey);
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package cn.stylefeng.roses.kernel.validator.constants;
|
||||
|
||||
/**
|
||||
* 图形验证码模块的常量
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:47
|
||||
*/
|
||||
public interface CaptchaConstants {
|
||||
|
||||
/**
|
||||
* 验证码 缓存前缀标识
|
||||
*/
|
||||
String CAPTCHA_CACHE_KEY_PREFIX = "KAPTCHA_KEY";
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package cn.stylefeng.roses.kernel.validator.pojo;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* EasyCaptcha 图形验证码参数
|
||||
*
|
||||
* @author fengshuonan
|
||||
* @date 2020/8/17 21:43
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class EasyCaptcha {
|
||||
|
||||
/**
|
||||
* 缓存Key
|
||||
*/
|
||||
private String verKey;
|
||||
|
||||
/**
|
||||
* Base64 图形验证码
|
||||
*/
|
||||
private String verImage;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
EasyCaptcha 图形验证码
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>kernel-d-validator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>validator-sdk-captcha</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--校验模块的api-->
|
||||
<dependency>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>validator-api</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--web模块-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--缓存模块的api-->
|
||||
<dependency>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>cache-api</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>cache-sdk-memory</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>cache-sdk-redis</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,52 @@
|
|||
package cn.stylefeng.roses.kemel.captcha;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi;
|
||||
import cn.stylefeng.roses.kernel.validator.CaptchaApi;
|
||||
import cn.stylefeng.roses.kernel.validator.pojo.EasyCaptcha;
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
|
||||
/**
|
||||
* 图形验证码实现
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:44
|
||||
*/
|
||||
public class CaptchaService implements CaptchaApi {
|
||||
|
||||
private final CacheOperatorApi<String> cacheOperatorApi;
|
||||
|
||||
public CaptchaService(CacheOperatorApi<String> cacheOperatorApi) {
|
||||
this.cacheOperatorApi = cacheOperatorApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EasyCaptcha captcha() {
|
||||
SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
|
||||
String verCode = specCaptcha.text().toLowerCase();
|
||||
String verKey = IdUtil.simpleUUID();
|
||||
cacheOperatorApi.put(verKey, verCode);
|
||||
return EasyCaptcha.builder().verImage(specCaptcha.toBase64()).verKey(verKey).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(String verCode, String verKey) {
|
||||
if (StrUtil.isAllEmpty(verKey, verCode)) {
|
||||
return false;
|
||||
}
|
||||
if (!verCode.trim().toLowerCase().equals(cacheOperatorApi.get(verKey))) {
|
||||
return false;
|
||||
}
|
||||
//删除缓存中验证码
|
||||
cacheOperatorApi.remove(verKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVerCode(String verKey) {
|
||||
return cacheOperatorApi.get(verKey);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package cn.stylefeng.roses.kemel.captcha.cache;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.stylefeng.roses.kernel.cache.AbstractMemoryCacheOperator;
|
||||
|
||||
import static cn.stylefeng.roses.kernel.validator.constants.CaptchaConstants.CAPTCHA_CACHE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 图形验证码缓存
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:44
|
||||
*/
|
||||
public class CaptchaMemoryCache extends AbstractMemoryCacheOperator<String> {
|
||||
|
||||
public CaptchaMemoryCache(TimedCache<String, String> timedCache) {
|
||||
super(timedCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommonKeyPrefix() {
|
||||
return CAPTCHA_CACHE_KEY_PREFIX;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package cn.stylefeng.roses.kemel.captcha.cache;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.stylefeng.roses.kernel.cache.AbstractMemoryCacheOperator;
|
||||
|
||||
import static cn.stylefeng.roses.kernel.validator.constants.CaptchaConstants.CAPTCHA_CACHE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 图形验证码缓存
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:44
|
||||
*/
|
||||
public class CaptchaRedisCache extends AbstractMemoryCacheOperator<Long> {
|
||||
|
||||
public CaptchaRedisCache(TimedCache<String, Long> timedCache) {
|
||||
super(timedCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommonKeyPrefix() {
|
||||
return CAPTCHA_CACHE_KEY_PREFIX;
|
||||
}
|
||||
|
||||
}
|
|
@ -45,6 +45,13 @@
|
|||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- captcha图形验证码 -->
|
||||
<dependency>
|
||||
<groupId>cn.stylefeng.roses</groupId>
|
||||
<artifactId>validator-sdk-captcha</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -6,9 +6,12 @@ import cn.stylefeng.roses.kemel.blackwhite.BlackListService;
|
|||
import cn.stylefeng.roses.kemel.blackwhite.WhiteListService;
|
||||
import cn.stylefeng.roses.kemel.blackwhite.cache.BlackListMemoryCache;
|
||||
import cn.stylefeng.roses.kemel.blackwhite.cache.WhiteListMemoryCache;
|
||||
import cn.stylefeng.roses.kemel.captcha.CaptchaService;
|
||||
import cn.stylefeng.roses.kemel.captcha.cache.CaptchaMemoryCache;
|
||||
import cn.stylefeng.roses.kemel.count.DefaultCountValidator;
|
||||
import cn.stylefeng.roses.kemel.count.cache.DefaultCountValidateCache;
|
||||
import cn.stylefeng.roses.kernel.validator.BlackListApi;
|
||||
import cn.stylefeng.roses.kernel.validator.CaptchaApi;
|
||||
import cn.stylefeng.roses.kernel.validator.CountValidatorApi;
|
||||
import cn.stylefeng.roses.kernel.validator.WhiteListApi;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
|
@ -68,4 +71,18 @@ public class ValidatorAutoConfiguration {
|
|||
return new WhiteListService(whiteListMemoryCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 图形验证码
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 11:25
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CaptchaApi.class)
|
||||
public CaptchaApi captchaApi() {
|
||||
TimedCache<String, String> timedCache = CacheUtil.newTimedCache(NONE_EXPIRED_TIME);
|
||||
CaptchaMemoryCache captchaMemoryCache = new CaptchaMemoryCache(timedCache);
|
||||
return new CaptchaService(captchaMemoryCache);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package cn.stylefeng.roses.kernel.system.modular.user.controller;
|
||||
|
||||
|
||||
import cn.stylefeng.roses.kernel.resource.api.annotation.ApiResource;
|
||||
import cn.stylefeng.roses.kernel.resource.api.annotation.GetResource;
|
||||
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
|
||||
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
|
||||
import cn.stylefeng.roses.kernel.validator.CaptchaApi;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 图形验证码
|
||||
*
|
||||
* @author chenjinlong
|
||||
* @date 2021/1/15 13:48
|
||||
*/
|
||||
@RestController
|
||||
@ApiResource(name = "用户登录图形验证码")
|
||||
public class KaptchaController {
|
||||
|
||||
@Resource
|
||||
private CaptchaApi captchaApi;
|
||||
|
||||
|
||||
@GetResource(name = "获取图形验证码", path = "/kaptcha", requiredPermission = false, requiredLogin = false)
|
||||
public ResponseData kaptcha() {
|
||||
return new SuccessResponseData(captchaApi.captcha());
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue