✨ Introducing new features. #1245 升级验证码实现支持 行为验证码

This commit is contained in:
lengleng committed 2020-05-19 13:27:46 +08:00
1 parent 4725c30dfc
commit 6a28df8884
8 files changed
+160 -42

No files matched your search

@@ -91,4 +91,9 @@ public interface CommonConstants {
* 默认存储bucket
*/
String BUCKET_NAME = "lengleng";
/**
* 滑块验证码
*/
String IMAGE_CODE_TYPE = "blockPuzzle";
}
+2 -2
View File
@@ -59,8 +59,8 @@
</dependency>
<!--验证码-->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!--hutool-->
@@ -0,0 +1,42 @@
package com.pig4cloud.pigx.gateway.config;
import com.anji.captcha.service.CaptchaCacheService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author lengleng
* @date 2020/5/19
* <p>
* 验证码 缓存提供支持集群
*/
@Primary
@Component
@AllArgsConstructor
public class CaptchaCacheServiceProvider implements CaptchaCacheService {
private final StringRedisTemplate stringRedisTemplate;
@Override
public void set(String key, String value, long expiresInSeconds) {
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
}
@Override
public boolean exists(String key) {
return stringRedisTemplate.hasKey(key);
}
@Override
public void delete(String key) {
stringRedisTemplate.delete(key);
}
@Override
public String get(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
}
@@ -17,10 +17,7 @@
package com.pig4cloud.pigx.gateway.config;
import com.pig4cloud.pigx.gateway.handler.ImageCodeHandler;
import com.pig4cloud.pigx.gateway.handler.SwaggerResourceHandler;
import com.pig4cloud.pigx.gateway.handler.SwaggerSecurityHandler;
import com.pig4cloud.pigx.gateway.handler.SwaggerUiHandler;
import com.pig4cloud.pigx.gateway.handler.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
@@ -39,16 +36,19 @@ import org.springframework.web.reactive.function.server.RouterFunctions;
@Configuration
@AllArgsConstructor
public class RouterFunctionConfiguration {
private final ImageCodeCheckHandler imageCodeCheckHandler;
private final ImageCodeCreateHandler imageCodeCreateHandler;
private final SwaggerResourceHandler swaggerResourceHandler;
private final SwaggerSecurityHandler swaggerSecurityHandler;
private final SwaggerUiHandler swaggerUiHandler;
private final ImageCodeHandler imageCodeHandler;
@Bean
public RouterFunction routerFunction() {
return RouterFunctions.route(
RequestPredicates.path("/code")
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), imageCodeHandler)
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), imageCodeCreateHandler)
.andRoute(RequestPredicates.POST("/check")
.and(RequestPredicates.accept(MediaType.ALL)), imageCodeCheckHandler)
.andRoute(RequestPredicates.GET("/swagger-resources")
.and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
@@ -18,13 +18,17 @@
package com.pig4cloud.pigx.gateway.filter;
import cn.hutool.core.util.StrUtil;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.constant.enums.LoginTypeEnum;
import com.pig4cloud.pigx.common.core.exception.ValidateCodeException;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.core.util.WebUtils;
import com.pig4cloud.pigx.gateway.config.FilterIgnorePropertiesConfig;
import lombok.AllArgsConstructor;
@@ -44,8 +48,8 @@ import reactor.core.publisher.Mono;
/**
* @author lengleng
* @date 2018/7/4
* 验证码处理
* @date 2020/5/19
* 登录逻辑验证码处理
*/
@Slf4j
@Component
@@ -125,6 +129,18 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
String randomStr = request.getQueryParams().getFirst("randomStr");
// 若是滑块登录
if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) {
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaVerification(code);
if (!captchaService.verification(vo).isSuccess()) {
throw new ValidateCodeException("验证码不能为空");
}
return;
}
//https://gitee.com/log4j/pig/issues/IWA0D
String mobile = request.getQueryParams().getFirst("mobile");
if (StrUtil.isNotBlank(mobile)) {
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.gateway.handler;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
/**
* @author lengleng
* @date 2020/5/19
* 验证码生成逻辑处理类
*/
@Slf4j
@Component
@AllArgsConstructor
public class ImageCodeCheckHandler implements HandlerFunction<ServerResponse> {
private final ObjectMapper objectMapper;
@Override
@SneakyThrows
public Mono<ServerResponse> handle(ServerRequest request) {
CaptchaVO vo = new CaptchaVO();
vo.setPointJson(request.queryParam("pointJson").get());
vo.setToken(request.queryParam("token").get());
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
ResponseModel responseModel = captchaService.check(vo);
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(objectMapper.writeValueAsString(R.ok(responseModel))));
}
}
@@ -17,58 +17,47 @@
package com.pig4cloud.pigx.gateway.handler;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.wf.captcha.ArithmeticCaptcha;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.concurrent.TimeUnit;
/**
* @author lengleng
* @date 2018/7/5
* @date 2020/5/19
* 验证码生成逻辑处理类
*/
@Slf4j
@Component
@AllArgsConstructor
public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
private static final Integer DEFAULT_IMAGE_WIDTH = 100;
private static final Integer DEFAULT_IMAGE_HEIGHT = 40;
private final RedisTemplate redisTemplate;
public class ImageCodeCreateHandler implements HandlerFunction<ServerResponse> {
private final ObjectMapper objectMapper;
@Override
@SneakyThrows
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
ArithmeticCaptcha captcha = new ArithmeticCaptcha(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT);
CaptchaVO vo = new CaptchaVO();
vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
ResponseModel responseModel = captchaService.get(vo);
String result = captcha.text();
//保存验证码信息
String randomStr = serverRequest.queryParam("randomStr").get();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.opsForValue().set(CacheConstants.DEFAULT_CODE_KEY + randomStr, result
, SecurityConstants.CODE_TIME, TimeUnit.SECONDS);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
captcha.out(os);
return ServerResponse
.status(HttpStatus.OK)
.contentType(MediaType.IMAGE_JPEG)
.body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray())));
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(objectMapper.writeValueAsString(R.ok(responseModel))));
}
}
+1 -1
View File
@@ -41,7 +41,7 @@
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot-admin.version>2.2.3</spring-boot-admin.version>
<hutool.version>5.3.3</hutool.version>
<kaptcha.version>1.6.2</kaptcha.version>
<kaptcha.version>1.1.8</kaptcha.version>
<swagger.fox.version>2.9.2</swagger.fox.version>
<knife4j.version>2.0.2</knife4j.version>
<velocity.version>1.7</velocity.version>