主要思路:因为是前后端分离,所以后端生成的验证码不能通过session直接拿到,所以后端生成的验证码会保存在redis中,前端登录时带上key和value,后端根据Key去redis取值,再和前端传进来的value对比,完成验证码验证。
1、添加 kaptcha的引用
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
2、添加kaptcha的配置文件
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class KaptcharConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.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", "110");
properties.setProperty("kaptcha.image.height", "40");
properties.setProperty("kaptcha.textproducer.font.size", "30");
properties.setProperty("kaptcha.session.key", "code");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
3、登录接口
@PostMapping(value = "/login")
public JSONResult login(@RequestParam("userName") String userName,
@RequestParam("passWord") String passWord,
@RequestParam("cToken") String cToken,
@RequestParam("verifyCode") String verifyCode) throws DeviceCloudException {
在接口内取redis的value进行比较。
4、获取验证码的接口
@Autowired
private DefaultKaptcha producer;
@ApiOperation(value = "获取验证码",notes= "获取验证码的接口")
@GetMapping(value = "/default")
public JSONResult generateVerificationCode() throws Exception {
Map<String, Object> map = new HashMap<>();
// 生成文字验证码
String text = producer.createText();
// 生成图片验证码
ByteArrayOutputStream outputStream = null;
BufferedImage image = producer.createImage(text);
outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", outputStream);
//
BASE64Encoder encoder = new BASE64Encoder();
String imageStr=encoder.encode(outputStream.toByteArray());
map.put("img",imageStr );
//生成验证码对应的token 以token为key 验证码为value存在redis中
String codeToken = NumberUtil.getStringRandom(16);
redisTemplate.opsForValue().set(codeToken, text, RedisConstant.VERIFY_CODE_EXPIRE_TIME, TimeUnit.MINUTES);
map.put("cToken", codeToken);
return JSONResult.ok(map);
}
注意,这里返回前端的是转成base64的图片,前端需要这样显示:
<img src="https://img-blog.csdnimg.cn/2022010710301536896.png"/>