1、后端使用工具生成二维码(包括image的字符串和code字符);
2、使用uuid生成唯一的key值,将key和code以键值对的形式存储到redis缓存中,设置过期时间;
3、将image字符串和key值发送给前端,前端将image字符串转换成图片渲染到页面;
4、将用户输入的验证码和接收的key值一起发送给后端;
5、后端使用key从redis中读取code值,(转大小写)进行比对;
6、比对成功执行相关操作,比对失败进行相关操作;
- @Service
- public class CheckCodeServiceImpl implements CheckCodeService {
- @Autowired
- RedisTemplate
redisTemplate; -
- @Override
- public CheckCode getCheckCode() {
- // 150、50为图形的长、宽。 4表示生成4位验证码,2表示干扰线是2位,并放入redis
- CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 50, 4, 2);
- //code验证码
- String codeValue = circleCaptcha.getCode();
- //图片验证码
- String imageBase64 = circleCaptcha.getImageBase64();
-
- //添加文件头部
- //"data:images/png;base64,"+imageBase64 直接显示
- String img = "data:images/png;base64," +imageBase64;
-
- //生成唯一key
- String uuid = UUID.randomUUID().toString();
- String key = uuid.replace("-", "");
-
- //存入redis,并设置过期时间
- redisTemplate.opsForValue().set(key, codeValue, 3, TimeUnit.MINUTES);
-
- //封装返回对象
- CheckCode checkCode = new CheckCode();
- checkCode.setCheckImg(img);
- checkCode.setCheckMessage(key);
- return checkCode;
- }
- }
- //js代码
-
- //验证
- const checkImg = ref("")
-
- const getCheckCode = async()=>{
- return request.get(`/checkCode/get`)
- }
-
-
- //html代码
-
- "login_span">
- 验证码:
-
"user.checkCode" style="width: 210px;height:40px;margin-bottom:30px;" placeholder="Please input" /> -
"width: 100px; height: 40px;margin-left: 10px;cursor:pointer;" :src="checkImg" :fit="fit"/>
- //登录
- const user = reactive({
- username: "",
- password: "",
- //输入的验证码
- checkCode:"",
- //key
- checkMessage:""
- })
-
- async function(){
- const {data} = await request.post(`/auth/login`,user)
- }
- @Override
- public String login(LoginDto loginDto) {
- //验证码验证
- String checkCode = loginDto.getCheckCode();
- String queryCode = redisTemplate.opsForValue().get(loginDto.getCheckMessage());
-
- //统一为小写比较
- String lowerCaseCheckCode = checkCode.toLowerCase();
- String lowerCasequeryCode = queryCode.toLowerCase();
- if(!lowerCaseCheckCode.equals(lowerCasequeryCode)){
- throw new RuntimeException("验证码错误");
- }
-
- //删除验证码缓存
- redisTemplate.delete(loginDto.getCheckMessage());
- //获取认证方法进行认证
- String username = loginDto.getUsername();
- LambdaQueryWrapper
queryWrapper = new LambdaQueryWrapper().eq(User::getUsername, username); - User user = userMapper.selectOne(queryWrapper);
- if(null == user){
- throw new RuntimeException("用户不存在");
- }
- //比较密码
- String passwordDb = user.getPassword();
- String password = loginDto.getPassword();
- boolean matches = passwordEncoder.matches(password, passwordDb);
- if(!matches){
- throw new RuntimeException("密码错误");
- }
-
- int id = user.getId();
- String userid = String.valueOf(id);
- //生成jwt
- String jwt = JwtUtils.createJWT(userid);
- //将用户信息转换成json数据
- String jsonString = JSON.toJSONString(user);
- //将用户信息存入redis
- redisTemplate.opsForValue().set("userId:"+userid,jsonString,30, TimeUnit.MINUTES);
- //返回给前端令牌
- return jwt;
- }