【validator-sdk-captcha】图形验证码模块【CaptchaController】图形验证码接口

pull/3/head
chenjinlong 2021-01-15 13:49:44 +08:00
parent 504aa0d1ed
commit ea0bc554ca
15 changed files with 316 additions and 8 deletions

View File

@ -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>

View File

@ -34,8 +34,12 @@ public class LoginRequest extends BaseRequest {
private Boolean rememberMe = false;
/**
*
*
*/
private String kaptcha;
private String verCode;
/**
* key
*/
private String verKey;
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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";
}

View File

@ -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;
}

View File

@ -0,0 +1 @@
EasyCaptcha 图形验证码

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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());
}
}