xp-robotaxi-account-boot/pom.xml
@@ -101,6 +101,10 @@ <scope>compile</scope> </dependency> <dependency> <groupId>pro.fessional</groupId> <artifactId>kaptcha</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency> xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/CaptchaConfig.java
New file @@ -0,0 +1,71 @@ package com.xiaopeng.account.config; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER; import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER_COLOR; import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_HEIGHT; import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_WIDTH; import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_COLOR; import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_IMPL; import static com.google.code.kaptcha.Constants.KAPTCHA_OBSCURIFICATOR_IMPL; import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_CONFIG_KEY; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE; import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_IMPL; /** * 验证码配置 * * @author ruoyi */ @Configuration public class CaptchaConfig { @Bean(name = "captchaProducer") public DefaultKaptcha getKaptchaBean() { DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty(KAPTCHA_BORDER, "yes"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); defaultKaptcha.setConfig(new Config(properties)); return defaultKaptcha; } @Bean(name = "captchaProducerMath") public DefaultKaptcha getKaptchaBeanMath() { DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty(KAPTCHA_BORDER, "yes"); properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.xiaopeng.account.config.KaptchaTextCreator"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); defaultKaptcha.setConfig(new Config(properties)); return defaultKaptcha; } } xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/KaptchaTextCreator.java
New file @@ -0,0 +1,55 @@ package com.xiaopeng.account.config; import com.google.code.kaptcha.text.impl.DefaultTextCreator; import java.util.Random; /** * 验证码文本生成器 * * @author ruoyi */ public class KaptchaTextCreator extends DefaultTextCreator { @Override public String getText() { int result; Random random = new Random(); int x = random.nextInt(10); int y = random.nextInt(10); StringBuilder suChinese = new StringBuilder(); int randomOperator = random.nextInt(3); if (randomOperator == 0) { result = x * y; suChinese.append(x); suChinese.append("*"); suChinese.append(y); } else if (randomOperator == 1) { if ((x != 0) && (y % x == 0)) { result = y / x; suChinese.append(y); suChinese.append("/"); suChinese.append(x); } else { result = x + y; suChinese.append(x); suChinese.append("+"); suChinese.append(y); } } else { if (x >= y) { result = x - y; suChinese.append(x); suChinese.append("-"); suChinese.append(y); } else { result = y - x; suChinese.append(y); suChinese.append("-"); suChinese.append(x); } } suChinese.append("=?@").append(result); return suChinese.toString(); } } xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/properties/CaptchaProperties.java
New file @@ -0,0 +1,42 @@ package com.xiaopeng.account.config.properties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; /** * 验证码配置 * * @author ruoyi */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.captcha") public class CaptchaProperties { /** * 验证码开关 */ private Boolean enabled; /** * 验证码类型(math 数组计算 char 字符) */ private String type; public Boolean getEnabled() { return enabled; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } public String getType() { return type; } public void setType(String type) { this.type = type; } } xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/CaptchaController.java
New file @@ -0,0 +1,30 @@ package com.xiaopeng.account.controller; import com.xiaopeng.account.service.IValidateCodeService; import com.xiaopeng.common.core.exception.CaptchaException; import com.xiaopeng.common.core.web.domain.AjaxResult; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; /** * 图形验证码控制器 * * @author ruoyi */ @RestController @RequiredArgsConstructor(onConstructor_ = @Lazy) public class CaptchaController { private final IValidateCodeService validateCodeService; @ApiOperation(value = "获取图形验证码", tags = {"管理后台-用户登录"}) @GetMapping("/base/v1/captcha") public AjaxResult captcha() throws CaptchaException, IOException { return validateCodeService.createCaptcha(); } } xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IValidateCodeService.java
New file @@ -0,0 +1,19 @@ package com.xiaopeng.account.service; import com.xiaopeng.common.core.exception.CaptchaException; import com.xiaopeng.common.core.web.domain.AjaxResult; import java.io.IOException; /** * 验证码处理 * * @author ruoyi */ public interface IValidateCodeService { /** * 生成验证码 */ AjaxResult createCaptcha() throws IOException, CaptchaException; } xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/ValidateCodeServiceImpl.java
New file @@ -0,0 +1,84 @@ package com.xiaopeng.account.service.impl; import com.google.code.kaptcha.Producer; import com.xiaopeng.account.config.properties.CaptchaProperties; import com.xiaopeng.account.service.IValidateCodeService; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.Constants; import com.xiaopeng.common.core.exception.CaptchaException; import com.xiaopeng.common.core.utils.sign.Base64; import com.xiaopeng.common.core.utils.uuid.IdUtils; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.redis.service.RedisService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.FastByteArrayOutputStream; import javax.annotation.Resource; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.concurrent.TimeUnit; /** * 验证码实现处理 * * @author ruoyi */ @Service public class ValidateCodeServiceImpl implements IValidateCodeService { @Resource(name = "captchaProducer") private Producer captchaProducer; @Resource(name = "captchaProducerMath") private Producer captchaProducerMath; @Autowired private RedisService redisService; @Autowired private CaptchaProperties captchaProperties; @Override public AjaxResult createCaptcha() throws IOException, CaptchaException { AjaxResult ajax = AjaxResult.success(); boolean captchaEnabled = Boolean.TRUE.equals(captchaProperties.getEnabled()); ajax.put("captchaEnabled", captchaEnabled); if (!captchaEnabled) { return ajax; } String uuid = IdUtils.simpleUUID(); String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; String capStr = null; String code = null; BufferedImage image = null; String captchaType = captchaProperties.getType(); if ("math".equals(captchaType)) { String capText = captchaProducerMath.createText(); capStr = capText.substring(0, capText.lastIndexOf("@")); code = capText.substring(capText.lastIndexOf("@") + 1); image = captchaProducerMath.createImage(capStr); } else { capStr = captchaProducer.createText(); code = capStr; image = captchaProducer.createImage(capStr); } redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { ImageIO.write(image, "jpg", os); } catch (IOException e) { return AjaxResult.error(e.getMessage()); } ajax.put("uuid", uuid); ajax.put("img", Base64.encode(os.toByteArray())); return ajax; } } xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/config/WebMvcConfig.java
@@ -12,7 +12,18 @@ public class WebMvcConfig implements WebMvcConfigurer { /** 不需要拦截地址 */ public static final String[] excludeUrls = { "/login", "/logout", "/refresh" }; public static final String[] excludeUrls = { "/login", "/logout", "/refresh", "/register", "/base/v1/login", "/base/v1/captcha", "/base/v1/operationPasswordLogin", "/base/v1/verificationCodeLogin", "/base/v1/getVerificationCode", "/base/v1/updatePassword" }; @Override public void addInterceptors(InterceptorRegistry registry) xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/CaptchaConfig.java
File was deleted xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/KaptchaTextCreator.java
File was deleted xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/RouterFunctionConfiguration.java
@@ -1,19 +1,13 @@ package com.xiaopeng.gateway.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import com.xiaopeng.gateway.handler.ValidateCodeHandler; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; @@ -35,17 +29,6 @@ private static final String ALLOWED_ORIGIN = "*"; private static final String ALLOWED_EXPOSE = "*"; private static final String MAX_AGE = "18000L"; @Autowired private ValidateCodeHandler validateCodeHandler; @SuppressWarnings("rawtypes") @Bean public RouterFunction routerFunction() { return RouterFunctions.route( RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), validateCodeHandler); } /** * 跨域配置 xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/handler/ValidateCodeHandler.java
File was deleted xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/ValidateCodeService.java
@@ -1,9 +1,6 @@ package com.xiaopeng.gateway.service; import java.io.IOException; import com.xiaopeng.common.core.exception.CaptchaException; import com.xiaopeng.common.core.web.domain.AjaxResult; /** * 验证码处理 @@ -11,11 +8,6 @@ * @author ruoyi */ public interface ValidateCodeService { /** * 生成验证码 */ public AjaxResult createCaptcha() throws IOException, CaptchaException; /** * 校验验证码 */ xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/impl/ValidateCodeServiceImpl.java
@@ -1,24 +1,11 @@ package com.xiaopeng.gateway.service.impl; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import javax.imageio.ImageIO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.FastByteArrayOutputStream; import com.google.code.kaptcha.Producer; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.Constants; import com.xiaopeng.common.core.exception.CaptchaException; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.utils.sign.Base64; import com.xiaopeng.common.core.utils.uuid.IdUtils; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.gateway.config.properties.CaptchaProperties; import com.xiaopeng.gateway.service.ValidateCodeService; /** @@ -28,62 +15,9 @@ */ @Service public class ValidateCodeServiceImpl implements ValidateCodeService { @Resource(name = "captchaProducer") private Producer captchaProducer; @Resource(name = "captchaProducerMath") private Producer captchaProducerMath; @Autowired private RedisService redisService; @Autowired private CaptchaProperties captchaProperties; /** * 生成验证码 */ @Override public AjaxResult createCaptcha() throws IOException, CaptchaException { AjaxResult ajax = AjaxResult.success(); boolean captchaEnabled = captchaProperties.getEnabled(); ajax.put("captchaEnabled", captchaEnabled); if (!captchaEnabled) { return ajax; } // 保存验证码信息 String uuid = IdUtils.simpleUUID(); String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; String capStr = null, code = null; BufferedImage image = null; String captchaType = captchaProperties.getType(); // 生成验证码 if ("math".equals(captchaType)) { String capText = captchaProducerMath.createText(); capStr = capText.substring(0, capText.lastIndexOf("@")); code = capText.substring(capText.lastIndexOf("@") + 1); image = captchaProducerMath.createImage(capStr); } else if ("char".equals(captchaType)) { capStr = code = captchaProducer.createText(); image = captchaProducer.createImage(capStr); } redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); // 转换流信息写出 FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { ImageIO.write(image, "jpg", os); } catch (IOException e) { return AjaxResult.error(e.getMessage()); } ajax.put("uuid", uuid); ajax.put("img", Base64.encode(os.toByteArray())); return ajax; } /** * 校验验证码