本文共 4646 字,大约阅读时间需要 15 分钟。
在SSM框架中,我们可以使用Redis存储验证码,解决后端和前端之间的验证问题。以下是详细的解决方案。
登录界面请求验证码:用户在登录界面提交账号和密码。此时,我们需要生成一个随机验证码,并将其以图片形式返回给前台客户端。
生成验证码并存储到Redis:后台生成随机验证码,将对应的verificationJwt令牌作为Redis的键,存储验证码作为值。
返回verificationJwt令牌:将刚生成的verificationJwt令牌放在响应头中,传送到前台客户端。
客户端验证:前台客户端将输入的验证码与Redis中存储的验证码进行对比,验证是否一致。
后端生成验证码并存储到Redis:
前端显示验证码:将base64图片发送到前台,展示给用户输入。
前台提交验证码:用户填写用户名、密码和验证码后,提交登录请求。
后端验证验证码:
前端代码:
后端代码:
配置文件:
// State.jsexport default { verificationJwt: null, options: [], activeIndex: '', showName: 'show', role: "nopass",}// Mutations.jssetVerificationJwt: (state, payload) => { state.verificationJwt = payload.verificationJwt;}// Getters.jsgetVerificationJwt: (state) => { return state.verificationJwt;}
// action.jsexport default { url: { SYSTEM_USER_DOLOGIN: '/vue/user/login', VERAIFICATION: '/vue/user/verificationCode' }}
// http.jsconst axios = require('axios').create({ baseURL: action.SERVER, headers: { 'verificationJwt': '', 'jwt': '' }});axios.interceptors.request.use((config) => { const verificationJwt = store.get('verificationJwt'); config.headers.verificationJwt = verificationJwt; config.headers.jwt = verificationJwt; return config;});axios.interceptors.response.use((response) => { const verificationJwt = response.headers.verificationJwt; if (verificationJwt) { store.commit('setVerificationJwt', { verificationJwt: verificationJwt }); } return response;});
// UserActionpublic String login(User user) { String verificationCode = request.getParameter("verificationCode"); String jwt = request.getHeader(JwtConstants.verificationJwt); Object redisVerificationCode = redisTemplate.opsForValue().get(jwt); if (StringUtils.isBlank(verificationCode)) { return ResponseUtil.error("验证码已超时"); } if (!StringUtils.equals(verificationCode.toLowerCase(), redisVerificationCode.toString().toLowerCase())) { return ResponseUtil.error("验证码错误"); } User loginUser = userService.login(user); if (loginUser != null) { Mapclaims = new HashMap<>(); claims.put("username", loginUser.getUsername()); claims.put("password", loginUser.getPassword()); String jwtToken = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL); response.setHeader(JwtConstants.verificationJwt, jwtToken); return ResponseUtil.success(loginUser); } else { return ResponseUtil.error("账号或密码错误"); }}
// ImageUtilpublic static String createImageWithVerifyCode(String word, int width, int height) { BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = bufferedImage.getGraphics(); graphics.setColor getRandomColor(160, 200); graphics.fillRect(0, 0, width, height); graphics.setColor(Color.white); graphics.drawRect(0, 0, width - 1, height - 1); Graphics2D graphics2d = (Graphics2D) graphics; Random random = new Random(); int x = 10; for (int i = 0; i < word.length(); i++) { graphics2d.setColor(new Color(random.nextInt(110) + 20, random.nextInt(110) + 20, random.nextInt(110) + 20)); int jiaodu = random.nextInt(60) - 30; double theta = jiaodu * Math.PI / 180; char c = word.charAt(i); graphics2d.rotate(theta, x, 20); graphics2d.drawString(String.valueOf(c), x, 20); graphics2d.rotate(-theta, x, 20); x += 30; } graphics.dispose(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "png", baos); byte[] bytes = baos.toByteArray(); BASE64Encoder encoder = new BASE64Encoder(); String pngBase64 = encoder.encodeBuffer(bytes).trim().replace("\\n", "").replace("\\r", ""); return pngBase64;}
redis.clients jedis ${redis.version}
通过以上方案,我们可以实现一个高效的RFC 7633规范的验证码登录系统,确保用户信息的安全性和访问的唯一性。
转载地址:http://qfoyk.baihongyu.com/