通用公共配置
生成验证码的两种方式,SpringBoot项目,下面是完整代码,直接就可以用
公共依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
|
配置 application.yml
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| spring: redis: host: localhost port: 6379 database: 0 password: timeout: 10s lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms
|
公共常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public class ConstantCode {
public static final String KAPTCHA_KEY = "ss:kaptcha"; public static final Long REDIS_EXP_TIME = 60 * 60L; public static final Long KAPTCHA_EXP_TIME = 60 * 3L;
public static final Integer WIDTH = 200; public static final Integer HEIGHT = 55;
public static final String IMG_JPG = "jpg"; public static final String IMG_PNG = "png"; public static final String IMG_JPEG = "jpeg";
}
|
Redis 序列化配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration public class RedisConfig { @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet();
return template; } }
|
Redis 工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
| import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils;
import java.util.Collection; import java.util.concurrent.TimeUnit;
@Component @SuppressWarnings("all") public class RedisUtils {
private static Logger logger = LoggerFactory.getLogger(RedisUtils.class);
@Autowired private RedisTemplate redisTemplate;
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); }
public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); }
public Collection<String> keys(final String pattern) { return redisTemplate.keys(pattern); }
public long deleteObject(final Collection collection) { return redisTemplate.delete(collection); }
public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { logger.error("RedisUtils expire(String key,long time) failure." + e.getMessage()); return false; } }
public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); }
public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { logger.error("RedisUtils hasKey(String key) failure." + e.getMessage()); return false; } }
public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } }
public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); }
public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { logger.error("RedisUtils set(String key,Object value) failure." + e.getMessage()); return false; } }
public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { logger.error("RedisUtils set(String key,Object value,long time) failure." + e.getMessage()); return false; } } }
|
通用返回结果封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; import java.util.HashMap;
public class Result extends HashMap<String, Object> { private static final long serialVersionUID = 1L;
public static final String CODE_TAG = "code";
public static final String MSG_TAG = "msg";
public static final String DATA_TAG = "data";
public Result() { }
public Result(int code, String msg) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); }
public Result(int code, String msg, Object data) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); if (!StringUtils.isEmpty(data)) { super.put(DATA_TAG, data); } }
public static Result success() { return Result.success("操作成功"); }
public static Result success(Object data) { return Result.success("操作成功", data); }
public static Result success(String msg) { return Result.success(msg, null); }
public static Result success(String msg, Object data) { return new Result(HttpStatus.OK.value(), msg, data); }
public static Result error() { return Result.error("操作失败"); }
public static Result error(String msg) { return Result.error(msg, null); }
public static Result error(String msg, Object data) { return new Result(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data); }
public static Result error(int code, String msg) { return new Result(code, msg, null); }
@Override public Result put(String key, Object value) { super.put(key, value); return this; } }
|
方法一:Graphics2D 画图实现
使用 jdk 画图 Graphics2D 生成验证码
1、验证码工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| import java.awt.*; import java.awt.image.BufferedImage; import java.util.Random;
public class VerifyCodeUtils {
public static String drawRandomText(BufferedImage bufferedImage, int width, int height) { Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics(); graphics.setColor(new Color(255, 255, 255)); graphics.fillRect(0, 0, width, height); graphics.setFont(new Font("宋体,楷体,微软雅黑", Font.BOLD, 35)); String baseNumLetter = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; StringBuilder builder = new StringBuilder(); int x = 40; String ch; Random random = new Random(); for (int i = 0; i < 4; i++) { graphics.setColor(getRandomColor()); int degree = random.nextInt() % 30; int dot = random.nextInt(baseNumLetter.length()); ch = baseNumLetter.charAt(dot) + ""; builder.append(ch); graphics.rotate(degree * Math.PI / 180, x, 45); graphics.drawString(ch, x, 45); graphics.rotate(-degree * Math.PI / 180, x, 45); x += 35; } for (int i = 0; i < 6; i++) { graphics.setColor(getRandomColor()); graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height)); } for (int i = 0; i < 30; i++) { int x1 = random.nextInt(width); int y1 = random.nextInt(height); graphics.setColor(getRandomColor()); graphics.fillRect(x1, y1, 2, 2); } return builder.toString(); }
private static Color getRandomColor() { Random ran = new Random(); return new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); } }
|
2、Controller 控制层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.FastByteArrayOutputStream; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Base64; import java.util.UUID;
@RestController public class VerificationController {
@Autowired private RedisUtils redisUtils;
@GetMapping("/getImageCode") public void getImageCode(HttpServletResponse response) throws IOException { response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); response.addHeader("Cache-Control", "post-check=0, pre-check=0"); response.setHeader("Pragma", "no-cache"); response.setContentType("image/png"); BufferedImage image = new BufferedImage(ConstantCode.WIDTH, ConstantCode.HEIGHT, BufferedImage.TYPE_INT_RGB); String randomText = VerifyCodeUtils.drawRandomText(image, ConstantCode.WIDTH, ConstantCode.HEIGHT); redisUtils.set(ConstantCode.KAPTCHA_KEY, randomText, ConstantCode.KAPTCHA_EXP_TIME); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, ConstantCode.IMG_JPG, out); out.flush(); out.close(); }
@GetMapping("/getCaptchaInfo") public Result getCaptchaInfo() { Result success = Result.success(); BufferedImage image = new BufferedImage(ConstantCode.WIDTH, ConstantCode.HEIGHT, BufferedImage.TYPE_INT_RGB); String uuid = UUID.randomUUID().toString().replace("-", ""); String verifyKey = ConstantCode.KAPTCHA_KEY + uuid; String randomText = VerifyCodeUtils.drawRandomText(image, ConstantCode.WIDTH, ConstantCode.HEIGHT); redisUtils.set(verifyKey, randomText, ConstantCode.KAPTCHA_EXP_TIME); FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { ImageIO.write(image, "jpg", os); } catch (IOException e) { return Result.error(e.getMessage()); } success.put("uuid", uuid); success.put("img", Base64.getEncoder().encodeToString(os.toByteArray())); return success; } }
|
方法二:kaptcha 依赖实现
1、验证码配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| 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.*;
@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"); Config config = new Config(properties); defaultKaptcha.setConfig(config); 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.test.demo.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"); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } }
|
2、验证码文本生成器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import com.google.code.kaptcha.text.impl.DefaultTextCreator; import java.util.Random;
public class KaptchaTextCreator extends DefaultTextCreator { private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override public String getText() { Integer result = 0; Random random = new Random(); int x = random.nextInt(10); int y = random.nextInt(10); StringBuilder suChinese = new StringBuilder(); int randomoperands = (int) Math.round(Math.random() * 2); if (randomoperands == 0) { result = x * y; suChinese.append(CNUMBERS[x]); suChinese.append("*"); suChinese.append(CNUMBERS[y]); } else if (randomoperands == 1) { if (!(x == 0) && y % x == 0) { result = y / x; suChinese.append(CNUMBERS[y]); suChinese.append("/"); suChinese.append(CNUMBERS[x]); } else { result = x + y; suChinese.append(CNUMBERS[x]); suChinese.append("+"); suChinese.append(CNUMBERS[y]); } } else if (randomoperands == 2) { if (x >= y) { result = x - y; suChinese.append(CNUMBERS[x]); suChinese.append("-"); suChinese.append(CNUMBERS[y]); } else { result = y - x; suChinese.append(CNUMBERS[y]); suChinese.append("-"); suChinese.append(CNUMBERS[x]); } } else { result = x + y; suChinese.append(CNUMBERS[x]); suChinese.append("+"); suChinese.append(CNUMBERS[y]); } suChinese.append("=?@" + result); return suChinese.toString(); } }
|
3、测试正码生成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import com.google.code.kaptcha.Producer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.FastByteArrayOutputStream; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Base64; import java.util.UUID;
@RestController public class CaptchaController { @Resource(name = "captchaProducer") private Producer captchaProducer;
@Resource(name = "captchaProducerMath") private Producer captchaProducerMath;
@Autowired private RedisUtils redisUtils;
@GetMapping("/captchaCharImage") public Result getCharCode() { Result ajax = Result.success(); String capText = captchaProducerMath.createText(); String capStr = capText.substring(0, capText.lastIndexOf("@")); String code = capText.substring(capText.lastIndexOf("@") + 1); BufferedImage image = captchaProducerMath.createImage(capStr); String uuid = UUID.randomUUID().toString().replace("-", ""); String verifyKey = ConstantCode.KAPTCHA_KEY + uuid; redisUtils.set(verifyKey, code, ConstantCode.KAPTCHA_EXP_TIME); FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { ImageIO.write(image, "jpg", os); } catch (IOException e) { return Result.error(e.getMessage()); } ajax.put("uuid", uuid); ajax.put("img", Base64.getEncoder().encodeToString(os.toByteArray())); return ajax; }
@GetMapping("/captchaMathImage") public Result getMathCode() { Result ajax = Result.success(); String capText = captchaProducer.createText(); BufferedImage image = captchaProducerMath.createImage(capText);
String uuid = UUID.randomUUID().toString().replace("-", ""); String verifyKey = ConstantCode.KAPTCHA_KEY + uuid; redisUtils.set(verifyKey, capText, ConstantCode.KAPTCHA_EXP_TIME); FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { ImageIO.write(image, "jpg", os); } catch (IOException e) { return Result.error(e.getMessage()); } ajax.put("uuid", uuid); ajax.put("img", Base64.getEncoder().encodeToString(os.toByteArray())); return ajax; } }
|