mirror of https://github.com/elunez/eladmin
代码优化,更换图形验证方式
parent
8cb7dc886f
commit
f26342ee0e
|
@ -1,8 +1,11 @@
|
|||
package me.zhengjie.redis;
|
||||
package me.zhengjie.config;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.parser.ParserConfig;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhengjie.utils.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
|
@ -19,6 +22,10 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
|||
import org.springframework.data.redis.core.RedisOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
|
@ -116,3 +123,71 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Value 序列化
|
||||
*
|
||||
* @author /
|
||||
* @param <T>
|
||||
*/
|
||||
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||
|
||||
private Class<T> clazz;
|
||||
|
||||
FastJsonRedisSerializer(Class<T> clazz) {
|
||||
super();
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException {
|
||||
if (t == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException {
|
||||
if (bytes == null || bytes.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
String str = new String(bytes, StandardCharsets.UTF_8);
|
||||
return JSON.parseObject(str, clazz);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写序列化器
|
||||
*
|
||||
* @author /
|
||||
*/
|
||||
class StringRedisSerializer implements RedisSerializer<Object> {
|
||||
|
||||
private final Charset charset;
|
||||
|
||||
StringRedisSerializer() {
|
||||
this(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private StringRedisSerializer(Charset charset) {
|
||||
Assert.notNull(charset, "Charset must not be null!");
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deserialize(byte[] bytes) {
|
||||
return (bytes == null ? null : new String(bytes, charset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Object object) {
|
||||
String string = JSON.toJSONString(object);
|
||||
if (StringUtils.isBlank(string)) {
|
||||
return null;
|
||||
}
|
||||
string = string.replace("\"", "");
|
||||
return string.getBytes(charset);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package me.zhengjie.config;
|
||||
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
import com.google.common.base.Predicates;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.schema.AlternateTypeRule;
|
||||
import springfox.documentation.schema.AlternateTypeRuleConvention;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||
|
||||
/**
|
||||
* api页面 /swagger-ui.html
|
||||
* @author Zheng Jie
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${swagger.enabled}")
|
||||
private Boolean enabled;
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
ParameterBuilder ticketPar = new ParameterBuilder();
|
||||
List<Parameter> pars = new ArrayList<>();
|
||||
ticketPar.name(tokenHeader).description("token")
|
||||
.modelRef(new ModelRef("string"))
|
||||
.parameterType("header")
|
||||
.defaultValue("Bearer ")
|
||||
.required(true)
|
||||
.build();
|
||||
pars.add(ticketPar.build());
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.enable(enabled)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.paths(Predicates.not(PathSelectors.regex("/error.*")))
|
||||
.build()
|
||||
.globalOperationParameters(pars);
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("eladmin 接口文档")
|
||||
.version("2.2")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Pageable转换展示在swagger中
|
||||
*/
|
||||
@Configuration
|
||||
class SwaggerDataConfig {
|
||||
|
||||
@Bean
|
||||
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
|
||||
return new AlternateTypeRuleConvention() {
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AlternateTypeRule> rules() {
|
||||
return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ApiModel
|
||||
static class Page {
|
||||
@ApiModelProperty("页码 (0..N)")
|
||||
private Integer page;
|
||||
|
||||
@ApiModelProperty("每页显示的数目")
|
||||
private Integer size;
|
||||
|
||||
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
|
||||
private List<String> sort;
|
||||
|
||||
public Integer getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(Integer page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Integer size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public List<String> getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void setSort(List<String> sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package me.zhengjie.exception;
|
|||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package me.zhengjie.exception;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
|
@ -12,16 +9,11 @@ import java.util.stream.IntStream;
|
|||
public class EntityExistException extends RuntimeException {
|
||||
|
||||
public EntityExistException(Class clazz, String field, String val) {
|
||||
super(EntityExistException.generateMessage(clazz.getSimpleName(), toMap(field, val)));
|
||||
super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
|
||||
}
|
||||
|
||||
private static String generateMessage(String entity, Map<Object, Object> saveBodyParams) {
|
||||
return StringUtils.capitalize(entity) +
|
||||
" 已存在 " +
|
||||
saveBodyParams;
|
||||
}
|
||||
|
||||
private static Map<Object, Object> toMap(String... entries) {
|
||||
return new HashMap<Object, Object>(){{ put(entries[0], entries[1]); }};
|
||||
private static String generateMessage(String entity, String field, String val) {
|
||||
return StringUtils.capitalize(entity)
|
||||
+ " with " + field + " "+ val + " existed";
|
||||
}
|
||||
}
|
|
@ -2,10 +2,6 @@ package me.zhengjie.exception;
|
|||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
* @date 2018-11-23
|
||||
|
@ -13,16 +9,11 @@ import java.util.stream.IntStream;
|
|||
public class EntityNotFoundException extends RuntimeException {
|
||||
|
||||
public EntityNotFoundException(Class clazz, String field, String val) {
|
||||
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), toMap(field, val)));
|
||||
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
|
||||
}
|
||||
|
||||
private static String generateMessage(String entity, Map<Object, Object> searchParams) {
|
||||
return StringUtils.capitalize(entity) +
|
||||
" 不存在 " +
|
||||
searchParams;
|
||||
}
|
||||
|
||||
private static Map<Object, Object> toMap(String... entries) {
|
||||
return new HashMap<Object, Object>(){{ put(entries[0], entries[1]); }};
|
||||
private static String generateMessage(String entity, String field, String val) {
|
||||
return StringUtils.capitalize(entity)
|
||||
+ " with " + field + " "+ val + " does not exist";
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
|||
@Data
|
||||
class ApiError {
|
||||
|
||||
private Integer status;
|
||||
private Integer status = 400;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime timestamp;
|
||||
private String message;
|
||||
|
@ -21,10 +21,17 @@ class ApiError {
|
|||
timestamp = LocalDateTime.now();
|
||||
}
|
||||
|
||||
ApiError(Integer status, String message) {
|
||||
this();
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
public static ApiError error(String message){
|
||||
ApiError apiError = new ApiError();
|
||||
apiError.setMessage(message);
|
||||
return apiError;
|
||||
}
|
||||
|
||||
public static ApiError error(Integer status, String message){
|
||||
ApiError apiError = new ApiError();
|
||||
apiError.setStatus(status);
|
||||
apiError.setMessage(message);
|
||||
return apiError;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,7 @@ import org.springframework.security.access.AccessDeniedException;
|
|||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.springframework.http.HttpStatus.*;
|
||||
|
||||
/**
|
||||
|
@ -31,8 +29,7 @@ public class GlobalExceptionHandler {
|
|||
public ResponseEntity handleException(Throwable e){
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,8 +39,7 @@ public class GlobalExceptionHandler {
|
|||
public ResponseEntity handleAccessDeniedException(AccessDeniedException e){
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
ApiError apiError = new ApiError(FORBIDDEN.value(),e.getMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
return buildResponseEntity(ApiError.error(FORBIDDEN.value(),e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,8 +49,7 @@ public class GlobalExceptionHandler {
|
|||
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
ApiError apiError = new ApiError(e.getStatus(),e.getMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,8 +59,7 @@ public class GlobalExceptionHandler {
|
|||
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,8 +69,7 @@ public class GlobalExceptionHandler {
|
|||
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
ApiError apiError = new ApiError(NOT_FOUND.value(),e.getMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,8 +80,8 @@ public class GlobalExceptionHandler {
|
|||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
|
||||
ApiError apiError = new ApiError(BAD_REQUEST.value(), str[1] + ":" + e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||
return buildResponseEntity(apiError);
|
||||
String message = str[1] + ":" + e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
||||
return buildResponseEntity(ApiError.error(message));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package me.zhengjie.redis;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Value 序列化
|
||||
*
|
||||
* @author /
|
||||
* @param <T>
|
||||
*/
|
||||
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||
|
||||
private Class<T> clazz;
|
||||
|
||||
FastJsonRedisSerializer(Class<T> clazz) {
|
||||
super();
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException {
|
||||
if (t == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException {
|
||||
if (bytes == null || bytes.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
String str = new String(bytes, StandardCharsets.UTF_8);
|
||||
return JSON.parseObject(str, clazz);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package me.zhengjie.redis;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import me.zhengjie.utils.StringUtils;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 重写序列化器
|
||||
*
|
||||
* @author /
|
||||
*/
|
||||
public class StringRedisSerializer implements RedisSerializer<Object> {
|
||||
|
||||
private final Charset charset;
|
||||
|
||||
StringRedisSerializer() {
|
||||
this(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private StringRedisSerializer(Charset charset) {
|
||||
Assert.notNull(charset, "Charset must not be null!");
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deserialize(byte[] bytes) {
|
||||
return (bytes == null ? null : new String(bytes, charset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Object object) {
|
||||
String string = JSON.toJSONString(object);
|
||||
if (StringUtils.isBlank(string)) {
|
||||
return null;
|
||||
}
|
||||
string = string.replace("\"", "");
|
||||
return string.getBytes(charset);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package me.zhengjie.swagger2;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* api页面 /swagger-ui.html
|
||||
* @author Zheng Jie
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${swagger.enabled}")
|
||||
private Boolean enabled;
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
ParameterBuilder ticketPar = new ParameterBuilder();
|
||||
List<Parameter> pars = new ArrayList<>();
|
||||
ticketPar.name(tokenHeader).description("token")
|
||||
.modelRef(new ModelRef("string"))
|
||||
.parameterType("header")
|
||||
.defaultValue("Bearer ")
|
||||
.required(true)
|
||||
.build();
|
||||
pars.add(ticketPar.build());
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.enable(enabled)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.paths(Predicates.not(PathSelectors.regex("/error.*")))
|
||||
.build()
|
||||
.globalOperationParameters(pars);
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("eladmin 接口文档")
|
||||
.version("2.2")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package me.zhengjie.swagger2;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.domain.Pageable;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
/**
* 将Pageable转换展示在swagger中
*/
@Configuration
public class SwaggerDataConfig {
@Bean
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
return new AlternateTypeRuleConvention() {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public List<AlternateTypeRule> rules() {
return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
}
};
}
@ApiModel
static class Page {
@ApiModelProperty("页码 (0..N)")
private Integer page;
@ApiModelProperty("每页显示的数目")
private Integer size;
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
private List<String> sort;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public List<String> getSort() {
return sort;
}
public void setSort(List<String> sort) {
this.sort = sort;
}
}
}
|
|
@ -68,7 +68,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
|
||||
String loginPath = "login";
|
||||
httpSecurity
|
||||
|
||||
// 禁用 CSRF
|
||||
|
@ -90,8 +89,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
"/**/*.js"
|
||||
).anonymous()
|
||||
|
||||
.antMatchers( HttpMethod.POST,"/auth/"+ loginPath).anonymous()
|
||||
.antMatchers("/auth/vCode").anonymous()
|
||||
.antMatchers(HttpMethod.POST,"/auth/login").anonymous()
|
||||
.antMatchers(HttpMethod.GET,"/auth/code").anonymous()
|
||||
// 支付宝回调
|
||||
.antMatchers("/api/aliPay/return").anonymous()
|
||||
.antMatchers("/api/aliPay/notify").anonymous()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package me.zhengjie.modules.security.rest;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.wf.captcha.ArithmeticCaptcha;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -12,7 +12,6 @@ import me.zhengjie.modules.security.security.AuthenticationInfo;
|
|||
import me.zhengjie.modules.security.security.AuthorizationUser;
|
||||
import me.zhengjie.modules.security.security.ImgResult;
|
||||
import me.zhengjie.modules.security.security.JwtUser;
|
||||
import me.zhengjie.modules.security.utils.VerifyCodeUtils;
|
||||
import me.zhengjie.utils.EncryptUtils;
|
||||
import me.zhengjie.modules.security.utils.JwtTokenUtil;
|
||||
import me.zhengjie.utils.SecurityUtils;
|
||||
|
@ -24,8 +23,6 @@ import org.springframework.security.authentication.AccountExpiredException;
|
|||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Zheng Jie
|
||||
|
@ -93,24 +90,16 @@ public class AuthenticationController {
|
|||
}
|
||||
|
||||
@ApiOperation("获取验证码")
|
||||
@GetMapping(value = "/vCode")
|
||||
public ImgResult getCode() throws IOException {
|
||||
|
||||
//生成随机字串
|
||||
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
|
||||
@GetMapping(value = "/code")
|
||||
public ImgResult getCode(){
|
||||
// 算术类型 https://gitee.com/whvse/EasyCaptcha
|
||||
ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);
|
||||
// 几位数运算,默认是两位
|
||||
captcha.setLen(2);
|
||||
// 获取运算的结果:5
|
||||
String result = captcha.text();
|
||||
String uuid = IdUtil.simpleUUID();
|
||||
redisService.saveCode(uuid,verifyCode);
|
||||
// 生成图片
|
||||
int w = 111, h = 36;
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
VerifyCodeUtils.outputImage(w, h, stream, verifyCode);
|
||||
try {
|
||||
return new ImgResult(Base64.encode(stream.toByteArray()),uuid);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
redisService.saveCode(uuid,result);
|
||||
return new ImgResult(captcha.toBase64(),uuid);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
package me.zhengjie.modules.security.utils;
|
||||
|
||||
import me.zhengjie.utils.StringUtils;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
/**
|
||||
* @author https://blog.csdn.net/ruixue0117/article/details/22829557
|
||||
* @date 2019-6-20 17:28:53
|
||||
*/
|
||||
public class VerifyCodeUtils{
|
||||
|
||||
//使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
|
||||
private static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
private static Random random = new Random();
|
||||
|
||||
|
||||
/**
|
||||
* 使用系统默认字符源生成验证码
|
||||
* @param verifySize 验证码长度
|
||||
* @return 验证码
|
||||
*/
|
||||
public static String generateVerifyCode(int verifySize){
|
||||
return generateVerifyCode(verifySize, VERIFY_CODES);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用指定源生成验证码
|
||||
* @param verifySize 验证码长度
|
||||
* @param sources 验证码字符源
|
||||
* @return 验证码
|
||||
*/
|
||||
private static String generateVerifyCode(int verifySize, String sources){
|
||||
if(StringUtils.isBlank(sources)){
|
||||
sources = VERIFY_CODES;
|
||||
}
|
||||
int codesLen = sources.length();
|
||||
Random rand = new Random(System.currentTimeMillis());
|
||||
StringBuilder verifyCode = new StringBuilder(verifySize);
|
||||
for(int i = 0; i < verifySize; i++){
|
||||
verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));
|
||||
}
|
||||
return verifyCode.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出指定验证码图片流
|
||||
* @param w /
|
||||
* @param h /
|
||||
* @param os /
|
||||
* @param code /
|
||||
* @throws IOException /
|
||||
*/
|
||||
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{
|
||||
int verifySize = code.length();
|
||||
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
Random rand = new Random();
|
||||
Graphics2D g2 = image.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
Color[] colors = new Color[5];
|
||||
Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,
|
||||
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
|
||||
Color.PINK, Color.YELLOW };
|
||||
float[] fractions = new float[colors.length];
|
||||
for(int i = 0; i < colors.length; i++){
|
||||
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
|
||||
fractions[i] = rand.nextFloat();
|
||||
}
|
||||
Arrays.sort(fractions);
|
||||
|
||||
g2.setColor(Color.GRAY);// 设置边框色
|
||||
g2.fillRect(0, 0, w, h);
|
||||
|
||||
Color c = getRandColor(200, 250);
|
||||
g2.setColor(c);// 设置背景色
|
||||
g2.fillRect(0, 2, w, h-4);
|
||||
|
||||
//绘制干扰线
|
||||
Random random = new Random();
|
||||
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int x = random.nextInt(w - 1);
|
||||
int y = random.nextInt(h - 1);
|
||||
int xl = random.nextInt(6) + 1;
|
||||
int yl = random.nextInt(12) + 1;
|
||||
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
|
||||
}
|
||||
|
||||
// 添加噪点
|
||||
float yawpRate = 0.05f;// 噪声率
|
||||
int area = (int) (yawpRate * w * h);
|
||||
for (int i = 0; i < area; i++) {
|
||||
int x = random.nextInt(w);
|
||||
int y = random.nextInt(h);
|
||||
int rgb = getRandomIntColor();
|
||||
image.setRGB(x, y, rgb);
|
||||
}
|
||||
|
||||
shear(g2, w, h, c);// 使图片扭曲
|
||||
|
||||
g2.setColor(getRandColor(100, 160));
|
||||
int fontSize = h-4;
|
||||
Font font = new Font("Algerian", Font.ITALIC, fontSize);
|
||||
g2.setFont(font);
|
||||
char[] chars = code.toCharArray();
|
||||
for(int i = 0; i < verifySize; i++){
|
||||
AffineTransform affine = new AffineTransform();
|
||||
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
|
||||
g2.setTransform(affine);
|
||||
g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);
|
||||
}
|
||||
|
||||
g2.dispose();
|
||||
ImageIO.write(image, "jpg", os);
|
||||
}
|
||||
|
||||
private static Color getRandColor(int fc, int bc) {
|
||||
if (fc > 255)
|
||||
fc = 255;
|
||||
if (bc > 255)
|
||||
bc = 255;
|
||||
int r = fc + random.nextInt(bc - fc);
|
||||
int g = fc + random.nextInt(bc - fc);
|
||||
int b = fc + random.nextInt(bc - fc);
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
|
||||
private static int getRandomIntColor() {
|
||||
int[] rgb = getRandomRgb();
|
||||
int color = 0;
|
||||
for (int c : rgb) {
|
||||
color = color << 8;
|
||||
color = color | c;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
private static int[] getRandomRgb() {
|
||||
int[] rgb = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb[i] = random.nextInt(255);
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
private static void shear(Graphics g, int w1, int h1, Color color) {
|
||||
shearX(g, w1, h1, color);
|
||||
shearY(g, w1, h1, color);
|
||||
}
|
||||
|
||||
private static void shearX(Graphics g, int w1, int h1, Color color) {
|
||||
int period = random.nextInt(2);
|
||||
int frames = 1;
|
||||
int phase = random.nextInt(2);
|
||||
for (int i = 0; i < h1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(0, i, w1, 1, (int) d, 0);
|
||||
g.setColor(color);
|
||||
g.drawLine((int) d, i, 0, i);
|
||||
g.drawLine((int) d + w1, i, w1, i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void shearY(Graphics g, int w1, int h1, Color color) {
|
||||
int period = random.nextInt(40) + 10; // 50;
|
||||
int frames = 20;
|
||||
int phase = 7;
|
||||
for (int i = 0; i < w1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(i, 0, 1, h1, 0, (int) d);
|
||||
g.setColor(color);
|
||||
g.drawLine(i, (int) d, i, 0);
|
||||
g.drawLine(i, (int) d + h1, i, h1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ spring:
|
|||
|
||||
redis:
|
||||
#数据库索引
|
||||
database: 1
|
||||
database: 0
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password:
|
||||
|
|
Loading…
Reference in New Issue