前端:
地址:ruoyi-ui/src/views/login.vue中的方法
下面这个就是登陆方法,看我注解。this.$store.dispatch是调用vuex中actions中的方法,是vuex相关知识。
handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; //判断是否勾选记住密码的操作 if (this.loginForm.rememberMe) { Cookies.set("username", this.loginForm.username, { expires: 30 }); Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }); Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }); } else { //没勾选直接移除就行了 Cookies.remove("username"); Cookies.remove("password"); Cookies.remove('rememberMe'); } //登陆方法 this.$store.dispatch("Login", this.loginForm).then(() => { this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); }).catch(() => { this.loading = false; if (this.captchaEnabled) { this.getCode(); } }); } }); }
进vuex,res是后端返回的数据,这块应该是把token存到cookies和vuex中了。前端大概就这样。
// 登录 Login({ commit }, userInfo) { const username = userInfo.username.trim() const password = userInfo.password const code = userInfo.code const uuid = userInfo.uuid return new Promise((resolve, reject) => { login(username, password, code, uuid).then(res => { //保存token setToken(res.token) commit('SET_TOKEN', res.token) resolve() }).catch(error => { reject(error) }) }) },
后端:
controller
/** * 登录方法 * * @param loginBody 登录信息 * @return 结果 */ @PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { AjaxResult ajax = AjaxResult.success(); // 生成令牌 String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid()); ajax.put(Constants.TOKEN, token); return ajax; }
service
我就说验证码校验,修改用户表,生成token,其他我也看不懂。
/** * 登录验证 * * @param username 用户名 * @param password 密码 * @param code 验证码 * @param uuid 唯一标识 * @return 结果 */ public String login(String username, String password, String code, String uuid) { // 验证码校验 validateCaptcha(username, code, uuid); // 登录前置校验 loginPreCheck(username, password); // 用户验证 Authentication authentication = null; try { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); AuthenticationContextHolder.setContext(authenticationToken); // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername authentication = authenticationManager.authenticate(authenticationToken); } catch (Exception e) { if (e instanceof BadCredentialsException) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); throw new UserPasswordNotMatchException(); } else { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); throw new ServiceException(e.getMessage()); } } finally { AuthenticationContextHolder.clearContext(); } //insert插入 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); LoginUser loginUser = (LoginUser) authentication.getPrincipal(); //修改用户表 recordLoginInfo(loginUser.getUserId()); // 生成token return tokenService.createToken(loginUser); }
验证码校验,从redis中拿不到验证码,就说明验证码过期了,没过期就直接删除,因为已经拿到验证码的值了,然后再判断验证码是否错误。
/** * 校验验证码 * * @param username 用户名 * @param code 验证码 * @param uuid 唯一标识 * @return 结果 */ public void validateCaptcha(String username, String code, String uuid) { boolean captchaEnabled = configService.selectCaptchaEnabled(); if (captchaEnabled) { String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); String captcha = redisCache.getCacheObject(verifyKey); //验证码过期 if (captcha == null) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); throw new CaptchaExpireException(); } //验证码拿到后就可以删除了 redisCache.deleteObject(verifyKey); //判断验证码是否错误 if (!code.equalsIgnoreCase(captcha)) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); throw new CaptchaException(); } } }
修改用户表,主要修改登陆ip,登录时间这两个。
/** * 记录登录信息 * * @param userId 用户ID */ public void recordLoginInfo(Long userId) { SysUser sysUser = new SysUser(); sysUser.setUserId(userId); //获取ip sysUser.setLoginIp(IpUtils.getIpAddr()); //获取当前时间 sysUser.setLoginDate(DateUtils.getNowDate()); //更新用户信息 userService.updateUserProfile(sysUser); }
生成token,其实把用户信息也存到redis中了,默认有效期半个小时,水平有限就这样吧
/** * 创建令牌 * * @param loginUser 用户信息 * @return 令牌 */ public String createToken(LoginUser loginUser) { String token = IdUtils.fastUUID(); loginUser.setToken(token); setUserAgent(loginUser); //刷新token,用户信息也会存到redis中,有效期半个小时(存验证码和登陆的用户信息) refreshToken(loginUser); Mapclaims = new HashMap<>(); claims.put(Constants.LOGIN_USER_KEY, token); return createToken(claims); }