1 工程概述
1.1 pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.71</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--kaptcha依赖包-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
1.2 application.yml
server:
port: 8000
spring:
redis:
host: 192.168.38.80
port: 6379
password: 123456
1.3 CaptchaConfig
@Configuration
public class CaptchaConfig {
/**
* 验证码配置 Kaptcha配置类名
*
*/
@Bean
public DefaultKaptcha kaptcha() {
DefaultKaptcha kaptcha = new DefaultKaptcha();
Properties properties = new Properties();
//验证码个数
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
//字体间隔
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "8");
//干扰线颜色
//干扰实现类
properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
//图片样式
properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.WaterRipple");
//文字来源
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789");
Config config = new Config(properties);
kaptcha.setConfig(config);
return kaptcha;
}
}
1.4 Util
package com.rosh.util;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
public final class HttpUtil {
private HttpUtil() {
}
private static final String UNKNOWN = "unknown";
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
ipAddress = InetAddress.getLocalHost().getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15 && ipAddress.contains(",")) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
}
package com.rosh.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* @Description:
* @Author: Rosh
* @Date: 2021/5/7 13:30
*/
public final class Md5Util {
private Md5Util(){
}
public static String md5(String data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
}
return sb.toString().toUpperCase();
} catch (Exception exception) {
return null;
}
}
}
1.5 CaptchaService
package com.rosh.service;
import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.rosh.util.HttpUtil;
import com.rosh.util.Md5Util;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* @Description:
* @Author: Rosh
* @Date: 2021/5/7 13:43
*/
@Service
public class CaptchaService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private DefaultKaptcha kaptcha;
public void generateCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
//生成验证码
String text = kaptcha.createText();
//获取key
String captchaKey = getCaptchaKey(request);
//设置5分钟过期
redisTemplate.opsForValue().set(captchaKey, text, 5, TimeUnit.MINUTES);
//返回
BufferedImage image = kaptcha.createImage(text);
ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(image, "jpg", outputStream);
outputStream.flush();
outputStream.close();
}
private String getCaptchaKey(HttpServletRequest request) {
String ip = HttpUtil.getIpAddr(request);
String userAgent = request.getHeader("User-Agent");
return "user:captcha:" + Md5Util.md5(ip + userAgent);
}
public JSONObject validateCaptcha(@NonNull String captcha, HttpServletRequest request) {
JSONObject rs = new JSONObject();
String captchaKey = getCaptchaKey(request);
String value = redisTemplate.opsForValue().get(captchaKey);
if (StringUtils.isBlank(value) || !value.equals(captcha)) {
rs.put("data", false);
rs.put("msg", "验证失败");
rs.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
} else {
rs.put("data", true);
rs.put("msg", "验证成功");
rs.put("code", HttpStatus.OK.value());
}
return rs;
}
}
1.6 CaptchaController
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
@Autowired
private CaptchaService captchaService;
@GetMapping("/generate")
public void generateCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
captchaService.generateCaptcha(request, response);
}
@GetMapping("/validate")
public JSONObject validateCaptcha(@RequestParam("captcha") String captcha, HttpServletRequest request) {
return captchaService.validateCaptcha(captcha, request);
}
}
1.7 启动类
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class);
}
}
2 测试