UID是唯一标识的字符串,下面是百度百科关于UUID的定义:
UUID是由一组32位数的16进制数字所构成,是故UUID理论上的总数为1632=2128,约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。
UUID的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的32个字符。示例:
550e8400-e29b-41d4-a716-446655440000
具体流程:
点击这个框,前端会生成一个UUID(这里是前端生成UUID的情况),
并且把这个UUID发送给后端,然后后端得到这个UUID后,后端自己再通过算法随机生成5位验证码字符串(比如上图的4xb22,这时候只是一串字符串)(如果UUID不是前端生成的,后端这时候也一起生成UUID)。
然后后端将这个字符串验证码和得到的UUID进行绑定(也就是说有这个UUID就能得到验证码字符串,可以理解是 key: “UUID”,value: “验证码字符串”)。
然后后端再通过其他算法(图像生成算法)将这个验证码字符串渲染成验证码图片。这时候,把这个图片发送给前端,后端在数据库中保存UUID和验证码字符串以及有效时间。
我们回到前端,当前端得到后端给的验证码图片后,显示在验证码该显示的地方。
然后用户开始输入验证码,当用户点击登录的时候,又发一次请求给后端,这个请求带有账号密码等信息,最重要的是,它还将UUID,和用户输入的验证码传给了后端。
然后后端拿到这些信息(UUID,验证码)后,就把这个UUID拿去查询它对应的字符串(K,V),将这个后端保存的验证码和前端发送来的验证码进行对比,如果对了,就验证成功,如果错了,就验证失败。
接口实习代码:
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_captcha")
@ApiModel(value = "SysCaptcha对象", description = "系统验证码")
public class SysCaptcha implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "uuid")
@TableId(value = "uuid", type = IdType.ID_WORKER)
private String uuid;
@ApiModelProperty(value = "验证码")
private String code;
@ApiModelProperty(value = "过期时间")
private Date expireTime;
}
@GetMapping("captcha.jpg")
public void captcha(HttpServletResponse response, String uuid) throws IOException {
try {
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
//获取图片验证码
BufferedImage image = sysCaptchaService.getCaptcha(uuid);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, Object> map = MapUtils.newHashMap();
map.put("code", 400);
map.put("msg", "验证码加载失败");
log.error("验证码加载失败:", e);
response.getWriter().println(JSON.toJSONString(map));
}
}
public interface SysCaptchaService extends IService<SysCaptcha> {
/**
* 获取图片验证码
*/
BufferedImage getCaptcha(String uuid);
/**
* 验证码效验
* @param uuid uuid
* @param code 验证码
* @return true:成功 false:失败
*/
boolean validate(String uuid, String code);
}
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.code.kaptcha.Producer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.awt.image.BufferedImage;
import java.util.Date;
@Service
public class SysCaptchaServiceImpl extends ServiceImpl<SysCaptchaMapper, SysCaptcha>
implements SysCaptchaService {
@Autowired
private Producer producer;
@Override
public BufferedImage getCaptcha(String uuid) {
if (StringUtils.isBlank(uuid)) {
throw new ApiException("uuid不能为空");
}
//生成文字验证码
String code = producer.createText();
SysCaptcha captchaEntity = new SysCaptcha();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//5分钟后过期
captchaEntity.setExpireTime(DateTimeUtils.addDateMinutes(new Date(), 5));
this.save(captchaEntity);
return producer.createImage(code);
}
@Override
public boolean validate(String uuid, String code) {
SysCaptcha captchaEntity = this.getOne(new QueryWrapper<SysCaptcha>().eq("uuid", uuid));
if (captchaEntity == null) {
return false;
}
//删除验证码
this.removeById(uuid);
if (captchaEntity.getCode().equalsIgnoreCase(code)
&& captchaEntity.getExpireTime().getTime() >= System.currentTimeMillis()) {
return true;
}
return false;
}
}
boolean captcha = sysCaptchaService.validate(userLoginRequest.getUuid(),
userLoginRequest.getCaptcha());
if (!captcha) {
return BaseResult.fail("验证码不正确"); }