mirror of https://gitee.com/maxjhandsome/pig
✨ Introducing new features. closed #I1P8ZX 验证码调整为EasyCaptcha
This commit is contained in:
parent
38802bfdf5
commit
6b36006685
|
@ -111,4 +111,8 @@ public interface SecurityConstants {
|
||||||
*/
|
*/
|
||||||
String DETAILS_LICENSE = "license";
|
String DETAILS_LICENSE = "license";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码有效期,默认 60秒
|
||||||
|
*/
|
||||||
|
long CODE_TIME = 60;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
|
|
||||||
* * <p>
|
|
||||||
* * Licensed under the GNU Lesser General Public License 3.0 (the "License");
|
|
||||||
* * you may not use this file except in compliance with the License.
|
|
||||||
* * You may obtain a copy of the License at
|
|
||||||
* * <p>
|
|
||||||
* * https://www.gnu.org/licenses/lgpl.html
|
|
||||||
* * <p>
|
|
||||||
* * Unless required by applicable law or agreed to in writing, software
|
|
||||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* * See the License for the specific language governing permissions and
|
|
||||||
* * limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.pig4cloud.pig.gateway.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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lengleng
|
|
||||||
* @date 2019/2/1
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class KaptchaConfiguration {
|
|
||||||
|
|
||||||
private static final String KAPTCHA_BORDER = "kaptcha.border";
|
|
||||||
|
|
||||||
private static final String KAPTCHA_TEXTPRODUCER_FONT_COLOR = "kaptcha.textproducer.font.color";
|
|
||||||
|
|
||||||
private static final String KAPTCHA_TEXTPRODUCER_CHAR_SPACE = "kaptcha.textproducer.char.space";
|
|
||||||
|
|
||||||
private static final String KAPTCHA_IMAGE_WIDTH = "kaptcha.image.width";
|
|
||||||
|
|
||||||
private static final String KAPTCHA_IMAGE_HEIGHT = "kaptcha.image.height";
|
|
||||||
|
|
||||||
private static final String KAPTCHA_TEXTPRODUCER_CHAR_LENGTH = "kaptcha.textproducer.char.length";
|
|
||||||
|
|
||||||
private static final Object KAPTCHA_IMAGE_FONT_SIZE = "kaptcha.textproducer.font.size";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认生成图形验证码宽度
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_IMAGE_WIDTH = "100";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认生成图像验证码高度
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_IMAGE_HEIGHT = "40";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认生成图形验证码长度
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_IMAGE_LENGTH = "4";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_COLOR_FONT = "black";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图片边框
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_IMAGE_BORDER = "no";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认图片间隔
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_CHAR_SPACE = "5";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码文字大小
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_IMAGE_FONT_SIZE = "30";
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DefaultKaptcha producer() {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.put(KAPTCHA_BORDER, DEFAULT_IMAGE_BORDER);
|
|
||||||
properties.put(KAPTCHA_TEXTPRODUCER_FONT_COLOR, DEFAULT_COLOR_FONT);
|
|
||||||
properties.put(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, DEFAULT_CHAR_SPACE);
|
|
||||||
properties.put(KAPTCHA_IMAGE_WIDTH, DEFAULT_IMAGE_WIDTH);
|
|
||||||
properties.put(KAPTCHA_IMAGE_HEIGHT, DEFAULT_IMAGE_HEIGHT);
|
|
||||||
properties.put(KAPTCHA_IMAGE_FONT_SIZE, DEFAULT_IMAGE_FONT_SIZE);
|
|
||||||
properties.put(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, DEFAULT_IMAGE_LENGTH);
|
|
||||||
Config config = new Config(properties);
|
|
||||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
|
||||||
defaultKaptcha.setConfig(config);
|
|
||||||
return defaultKaptcha;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -21,7 +21,7 @@ package com.pig4cloud.pig.gateway.filter;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.pig4cloud.pig.common.core.constant.CommonConstants;
|
import com.pig4cloud.pig.common.core.constant.CacheConstants;
|
||||||
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||||
import com.pig4cloud.pig.common.core.exception.ValidateCodeException;
|
import com.pig4cloud.pig.common.core.exception.ValidateCodeException;
|
||||||
import com.pig4cloud.pig.common.core.util.R;
|
import com.pig4cloud.pig.common.core.util.R;
|
||||||
|
@ -81,8 +81,7 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
|
||||||
|
|
||||||
// 校验验证码
|
// 校验验证码
|
||||||
checkCode(request);
|
checkCode(request);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
|
response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
|
||||||
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
@ -94,8 +93,7 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
|
||||||
DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
|
DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
|
||||||
|
|
||||||
monoSink.success(dataBuffer);
|
monoSink.success(dataBuffer);
|
||||||
}
|
} catch (JsonProcessingException jsonProcessingException) {
|
||||||
catch (JsonProcessingException jsonProcessingException) {
|
|
||||||
log.error("对象输出异常", jsonProcessingException);
|
log.error("对象输出异常", jsonProcessingException);
|
||||||
monoSink.error(jsonProcessingException);
|
monoSink.error(jsonProcessingException);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +106,7 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查code
|
* 检查code
|
||||||
|
*
|
||||||
* @param request
|
* @param request
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
|
@ -123,7 +122,7 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
|
||||||
randomStr = request.getQueryParams().getFirst("mobile");
|
randomStr = request.getQueryParams().getFirst("mobile");
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = CommonConstants.DEFAULT_CODE_KEY + randomStr;
|
String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
|
||||||
if (!redisTemplate.hasKey(key)) {
|
if (!redisTemplate.hasKey(key)) {
|
||||||
throw new ValidateCodeException("验证码不合法");
|
throw new ValidateCodeException("验证码不合法");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||||
*
|
*
|
||||||
* * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* * <p>
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Licensed under the GNU Lesser General Public License 3.0 (the "License");
|
|
||||||
* * you may not use this file except in compliance with the License.
|
|
||||||
* * You may obtain a copy of the License at
|
|
||||||
* * <p>
|
|
||||||
* * https://www.gnu.org/licenses/lgpl.html
|
|
||||||
* * <p>
|
|
||||||
* * Unless required by applicable law or agreed to in writing, software
|
|
||||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* * See the License for the specific language governing permissions and
|
|
||||||
* * limitations under the License.
|
|
||||||
*
|
*
|
||||||
|
* 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.pig.gateway.handler;
|
package com.pig4cloud.pig.gateway.handler;
|
||||||
|
|
||||||
import com.google.code.kaptcha.Producer;
|
import com.pig4cloud.pig.common.core.constant.CacheConstants;
|
||||||
import com.pig4cloud.pig.common.core.constant.CommonConstants;
|
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
|
||||||
import lombok.RequiredArgsConstructor;
|
import com.wf.captcha.ArithmeticCaptcha;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.core.io.buffer.DefaultDataBuffer;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -35,55 +35,40 @@ import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lengleng
|
* @author lengleng
|
||||||
* @date 2019/2/1 验证码生成逻辑处理类
|
* @date 2018/7/5
|
||||||
|
* 验证码生成逻辑处理类
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
|
public class ImageCodeHandler implements HandlerFunction<ServerResponse> {
|
||||||
|
private static final Integer DEFAULT_IMAGE_WIDTH = 100;
|
||||||
private final Producer producer;
|
private static final Integer DEFAULT_IMAGE_HEIGHT = 40;
|
||||||
|
|
||||||
private final RedisTemplate redisTemplate;
|
private final RedisTemplate redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
|
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
|
||||||
final String randomStr = serverRequest.queryParam("randomStr").get();
|
ArithmeticCaptcha captcha = new ArithmeticCaptcha(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT);
|
||||||
|
|
||||||
return ServerResponse.status(HttpStatus.OK).contentType(MediaType.IMAGE_JPEG)
|
String result = captcha.text();
|
||||||
.body(BodyInserters.fromDataBuffers(Mono.create(monoSink -> {
|
|
||||||
try {
|
|
||||||
byte[] bytes = createCodeImage(randomStr);
|
|
||||||
DefaultDataBuffer dataBuffer = new DefaultDataBufferFactory().wrap(bytes);
|
|
||||||
|
|
||||||
monoSink.success(dataBuffer);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
log.error("ImageIO write err", e);
|
|
||||||
monoSink.error(e);
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] createCodeImage(String randomStr) throws IOException {
|
|
||||||
// 生成验证码
|
|
||||||
String text = producer.createText();
|
|
||||||
BufferedImage image = producer.createImage(text);
|
|
||||||
|
|
||||||
//保存验证码信息
|
//保存验证码信息
|
||||||
redisTemplate.opsForValue().set(CommonConstants.DEFAULT_CODE_KEY + randomStr, text, 60, TimeUnit.SECONDS);
|
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();
|
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
||||||
ImageIO.write(image, "jpeg", os);
|
captcha.out(os);
|
||||||
return os.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return ServerResponse
|
||||||
|
.status(HttpStatus.OK)
|
||||||
|
.contentType(MediaType.IMAGE_JPEG)
|
||||||
|
.body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue