2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 若依-用户长时间未修改密码强制修改

若依-用户长时间未修改密码强制修改

时间:2020-09-12 00:58:11

相关推荐

若依-用户长时间未修改密码强制修改

需求原因

用户长期未修改密码可能存在密码安全问题,项目要求提供一个配置使用户一定时间间隔就修改密码

要求

后端登录时判断是否达到最大间隔时间,达到则修改用户的constraint字段(方便前端判断);

登录验证后,判断是否需要修改密码,需要修改则阻止跳转、弹出修改框;

限制:新密码不能与旧密码一致;

修改完成后正常跳转到主页面;

数据库更新密码、维护constraint字段。

后端实现

判断是否要求强制修改密码

src\main\java\com\ruoyi\framework\web\service\UserDetailsServiceImpl.java

修改前

@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{SysUser user = userService.selectUserByUserName(username);if (StringUtils.isNull(user)){log.info("登录用户:{} 不存在.", username);throw new ServiceException("登录用户:" + username + " 不存在");}else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())){log.info("登录用户:{} 已被删除.", username);throw new ServiceException("对不起,您的账号:" + username + " 已被删除");}else if (UserStatus.DISABLE.getCode().equals(user.getStatus())){log.info("登录用户:{} 已被停用.", username);throw new ServiceException("对不起,您的账号:" + username + " 已停用");}return createLoginUser(user);}

修改后

// 新增自动装配@Autowiredprivate SysConfigMapper sysConfigMapper;@Autowiredprivate SysUserMapper userMapper;// 代码修改@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{SysUser user = userService.selectUserByUserName(username);if (StringUtils.isNull(user)){log.info("登录用户:{} 不存在.", username);throw new ServiceException("登录用户:" + username + " 不存在");}else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())){log.info("登录用户:{} 已被删除.", username);throw new ServiceException("对不起,您的账号:" + username + " 已被删除");}else if (UserStatus.DISABLE.getCode().equals(user.getStatus())){log.info("登录用户:{} 已被停用.", username);throw new ServiceException("对不起,您的账号:" + username + " 已停用");}// 用户信息没有密码最后修改日期,则直接强制修改密码if (user.getPassTime() == null) {user.setConstraint(true);} else {// 有最后修改日期则再进行判断// 获取最大密码修改时间间隔(毫秒值)// 若依已经写好的方法,直接拿来用就行SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("sys.user.pass.interval");Long interval = Long.parseLong(sysConfig.getConfigValue()) * 24 * 60 * 60 * 1000;// 获取用户密码修改间隔Long userInterval = System.currentTimeMillis() - user.getPassTime().getTime();// 如果用户间隔超过间隔上限则要求强制修改密码if (userInterval >= interval) {user.setConstraint(true);}}// 保存到数据库// 若依已经写好的用户信息更新userMapper.updateUser(user);return createLoginUser(user);}

通过constraint判断修改密码场景(强制还是自主)

src\main\java\com\ruoyi\web\controller\system\SysProfileController.java

修改前

// 修改前源码// Javabean记得新增constraint属性和get、set// userMapper.xml记得修改一下返回字段/*** 重置密码*/@Log(title = "个人信息", businessType = BusinessType.UPDATE)@PutMapping("/updatePwd")public AjaxResult updatePwd(String oldPassword, String newPassword){LoginUser loginUser = getLoginUser();String userName = loginUser.getUsername();String password = loginUser.getPassword();if (!SecurityUtils.matchesPassword(oldPassword, password)){return AjaxResult.error("修改密码失败,旧密码错误");}if (SecurityUtils.matchesPassword(newPassword, password)){return AjaxResult.error("新密码不能与旧密码相同");}if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0){// 更新缓存用户密码loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));tokenService.setLoginUser(loginUser);return AjaxResult.success();}return AjaxResult.error("修改密码异常,请联系管理员");}

修改后

// 修改后代码/*** 重置密码*/@Log(title = "个人信息", businessType = BusinessType.UPDATE)@PutMapping("/updatePwd")public AjaxResult updatePwd(@RequestBody Map<String, Object> user) {// 获取constraintboolean constraint = (boolean) user.get("constraint");// 防止传参异常或维护时出现问题constraint = constraint == true ? constraint : false;LoginUser loginUser = getLoginUser();String userName = loginUser.getUsername();String password = loginUser.getPassword();// 获取旧密码(为了不影响若依中原有的密码修改)String oldPassword = (String) user.get("oldPassword");// 获取新密码String newPassword = (String) user.get("newPassword");// 强制修改密码时不用判断旧密码if (!constraint && !SecurityUtils.matchesPassword(oldPassword, password)) {System.out.println("旧密码");return AjaxResult.error("修改密码失败,旧密码错误");}if (SecurityUtils.matchesPassword(newPassword, password)) {System.out.println("新密码");return AjaxResult.error("新密码不能与旧密码相同");}if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {// 更新缓存用户密码loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));tokenService.setLoginUser(loginUser);return AjaxResult.success();}return AjaxResult.error("修改密码异常,请联系管理员");}

逻辑改变不大:

新增判断——强制修改时不比判断旧密码(传空就行);

接收类型:

这是由于开发过程中出现了一些问题、bug,排查过程中将入参类型修改了一下;

新增接收参数:constraint(true:强制修改密码,false:不强制)

前端实现

ruoyi-ui\src\views\login.vue

// 新增弹出框标签<el-dialog title="您的密码已长时间未修改,请修改密码" :visible.sync="loginInfo.constraint"><el-form><el-form-item label="新密码"><el-input v-model="newPassword" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="updatePwd">确 定</el-button></div></el-dialog>// 导入方法import { updateUserPwd } from "@/api/system/user";//新增对象、变量loginInfo:{constraint: false},newPassword:'',// 修改登录方法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((res) => {getInfo().then(loginInfo => {this.loginInfo = loginInfo.user// 如果返回的constraint为false则正常跳转到主页面if(!this.loginInfo.constraint) {this.$router.push({ path: this.redirect || "/" }).catch(() => {});} else {// 否则设置constraint值为true,使页面不能跳转到主页面localStorage.setItem('constraint', true)}}).catch(() => {})// const md5passwod = md5(this.loginForm.password);// console.log("md5passwod" + md5passwod);//用于后续解锁// localStorage.setItem("username", this.loginForm.username);}).catch(() => {this.loading = false;if (this.captchaOnOff) {this.getCode();}});}});},// 新增修改方法updatePwd(){updateUserPwd("", this.newPassword, true).then(response => {// 修改完成将constraint改为falselocalStorage.setItem('constraint', false)this.$modal.msgSuccess("修改成功");this.$router.push({ path: this.redirect || "/" }).catch(() => {});}).catch((e) => {console.info(e)});},

ruoyi-ui\src\api\system\user.js

// 新增constraint属性// 用户密码重置export function updateUserPwd(oldPassword, newPassword, constraint) {const data = {oldPassword,newPassword,constraint}return request({url: '/system/user/profile/updatePwd',method: 'put',data: data})}

ruoyi-ui\src\permission.js

修改前

if (getToken()) {to.meta.title && store.dispatch('settings/setTitle', to.meta.title)/* has token*/if (to.path === '/login') {next({ path: '/' })NProgress.done()

// 修改后if (getToken()) {to.meta.title && store.dispatch('settings/setTitle', to.meta.title)/* has token*/// localStorage.setItem('constraint',false)if (to.path === '/login') {// 新增判断——当前位置未登录页面时:如果constraint值为trueif(localStorage.getItem("constraint") == 'true') {// 去掉tokensetToken("")}// 不为true时不变next({ path: '/' })NProgress.done()

ruoyi-ui\src\views\system\user\profile\resetPwd.vue

submit() {this.$refs["form"].validate(valid => {if (valid) {// 修改updateUserPwd方法的入参// constraint值为true时不校验旧密码,传入false校验,不影响功能updateUserPwd(this.user.oldPassword, this.user.newPassword, false).then(response => {this.$modal.msgSuccess("修改成功");});}});},

展示

遇到的问题

用户不必更改密码,直接刷新页面就会进入到主页面

这样一来我做的强制修改密码就不强制了,那怎么忍得了,这还是我一时兴起点了一下刷新试了试,结果果然直接跳过强制修改了

解决方案、想法

如果constraint字段为true(即需要强制修改密码),将token设空,这样刷新就不会跳转到主页面

但是这样处理的时候就出现了一个问题(困扰了大半个小时,改了不少地方——尤其是后端的接收类型我都改成Map了……)

没错!修改密码这里需要token的校验,我把token清空了就无法正常调用了

解决(1)

解决(2)

新增需求

密码强度校验级别

src\main\java\com\ruoyi\web\controller\system\SysProfileController.java

// 新增代码// 获取密码强度SysConfig sysConfig = configMapper.checkConfigKeyUnique("sys.user.pass.strength");String strength = sysConfig.getConfigValue();Pattern p;boolean strengthEnough = false;switch (strength) {// 强度3:必须含有特殊字符case "3":// 非数字、字母p = pile("[A-Za-z0-9]");for (int i = 0; i < newPassword.length(); i++) {if (!p.matcher(newPassword.substring(i, i + 1)).find()) {strengthEnough = true;break;}}if (!strengthEnough) {return AjaxResult.error("新密码必须含特殊字符");}// 强度2:必须含有大写和小写case "2":strengthEnough = false;// 含大写字母p = pile("^[A-Z]+$");for (int i = 0; i < newPassword.length(); i++) {if (p.matcher(newPassword.substring(i, i + 1)).find()) {// 含小写字母p = pile("^[a-z]+$");for (int j = 0; j < newPassword.length(); j++) {if (p.matcher(newPassword.substring(j, j + 1)).find()) {strengthEnough = true;break;}}// 通过直接结束循环if (strengthEnough) {break;}}}if (!strengthEnough) {return AjaxResult.error("新密码必须含大写和小写");}// 强度1:密码至少6位case "1":if (newPassword.length() < 6) {return AjaxResult.error("新密码至少6位");}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。