【Vue管理后台】用户登录强制修改密码

【Ruoyi管理后台】用户登录强制修改密码 这篇文章已经实现了这个需求,因为个人业务中强制改密页面是进入系统且浮动于其他页面上方,进入强制改密页面的同时其他页面会向后台请求,如果清空token后会造成其他的请求失败。本文整体步骤与参考博文一致,详细步骤请参考【Ruoyi管理后台】用户登录强制修改密码 这篇文章,本文只是对某些方法进行了简单修改,进入强制改密页面时不清空token,使用Vue的路由守卫来拦截未修改密码的用户访问系统的特定页面。

一、login.vue页面修改

调整 handleLogin 函数,不必暂存token,而是存储res_code和rest_sign。

javascript 复制代码
this.$store.dispatch("Login", this.loginForm).then((res) => {
   if (res.res_code && res.res_code === 1001) {// 判断到后端接口返回的重置密码标识码
        // 设置res_code与res_sign,守卫路由获取判断使用
          localStorage.setItem("res_code", 1001);
          localStorage.setItem("res_sign", response.reset_sign);
         // 重定向到重置密码页,并带上校验参数
         this.redirect = '/reset?' + 'sign=' + res.reset_sign + '&username=' + this.loginForm.username;
       }
       this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
     }).catch(() => {
            this.loading = false;
            if (this.captchaOnOff) {
              this.getCode();
            }
     });

二、强制改密页面修改

强制改密页面对博文中页面进行了简单修改,进入页面后不用清空token,增加了统一的关闭窗口方法closeWin,修改成功与取消修改时清空设置内容与token,跳转到登录页面。

html 复制代码
<template>

	<el-dialog :close-on-click-modal="false" title="密码过期,请修改密码" :visible.sync="thisVisible" width="600px" append-to-body :show-close="false">
	  <el-form ref="resetForm" :model="resetForm" :rules="secretRules" label-width="80px">
	    <el-row>
	      <el-col :span="18">
	        <el-form-item  label="旧密码" prop="oldPassword">
				<el-input v-model="resetForm.oldPassword" placeholder="请输入旧密码" type="password" :type="oldflagType" maxlength="20" auto-complete="off">
					<i slot="suffix"
					   :class="this.oldflag?'mdi mdi-eye':'mdi mdi-eye-off'"
					   style="margin-top: 8px;font-size: 18px;"
					   @click="getoldFlag()"></i>
				</el-input>
	        </el-form-item>
	      </el-col>
	    </el-row>
	    <el-row>
	      <el-col :span="18" style="margin-top: 5px">
	        <el-form-item label="新密码" prop="newPassword">
	          <el-input v-model="resetForm.newPassword" placeholder="请输入新密码" type="password" :type="flagType" maxlength="20" auto-complete="off">
				  <i slot="suffix"
				  :class="this.flag?'mdi mdi-eye':'mdi mdi-eye-off'"
				  style="margin-top: 8px;font-size: 18px;"
					 @click="getFlag()"></i>
			  </el-input>
	        </el-form-item>
	      </el-col>
	    </el-row>
		<el-row>
		  <el-col :span="18" style="margin-top: 5px">
		    <el-form-item label="确认密码" prop="confirmPassword">
				<el-input v-model="resetForm.confirmPassword" placeholder="请再次输入新密码" type="password" :type="reflagType" maxlength="20" auto-complete="off">
					<i slot="suffix"
					   :class="this.reflag?'mdi mdi-eye':'mdi mdi-eye-off'"
					   style="margin-top: 8px;font-size: 18px;"
					   @click="getreFlag()"></i>
				</el-input>
		    </el-form-item>
		  </el-col>
		</el-row>
	  </el-form>
	  <div slot="footer" class="dialog-footer">
	    <el-button type="primary" @click="submitForm">确 定</el-button>
	    <el-button @click="closeWin" >取 消</el-button>
	  </div>
	</el-dialog>

</template>

<script>
import { resetUserProfilePwd } from "@/api/system/user";
import { setToken } from '@/utils/auth'

import { updateUserPwd } from "@/api/system/user";
import { getCodeImg } from "@/api/login";
import {MessageBox} from "element-ui";
import store from "@/store/store";
export default {
    name: 'serviceDialog',

  watch:{
    sdVasible:{
      handler(newValue){
        this.thisVisible = true;
      }
    }
  },
    data() {
      const equalToPassword = (rule, value, callback) => {
        if (this.resetForm.newPassword !== value) {
          callback(new Error("两次输入的密码不一致"));
        } else {
          // const reg = /^(?![A-z0-9]+$)(?![A-z~!@#$%^&*()_+]+$)(?![0-9~!@#$%^&*()_+]+$)([A-z0-9~!@#$%^&*()_+]{12,})/g
          // if (!reg.test(value)) {
          //   callback(new Error("输入的密码必须包含数字、大小写字母、符号"));
          // }
          callback();
        }
      };
        return {
        	oldflag: false,
          oldflagType: 'password',
          flag: false,
          flagType: 'password',
          reflag: false,
          reflagType: 'password',
          thisVisible:true,
          resetForm: {
            username: "",
            oldPassword: "",
            newPassword: "",
            confirmPassword: "",
            code: "",
            sign: "",
            uuid: ""
          },
            serviceSelectList: [],
            secretRules: {
              oldPassword: [{
                        required: true,
                        message: '请输入旧密码',
                        trigger: 'blur'
                    }],
              newPassword: [
                      { required: true, message: "新密码不能为空", trigger: "blur" },
                      { pattern: /(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9]).{8,20}/,
                        message: '新密码长度必须介于 8 和 20 之间,并且包含大写字母、小写字母、数字、特殊字符',  trigger: "blur" }
                    ],
              confirmPassword: [
                    	{ required: true, message: "再次输入新密码", trigger: "blur" },
                      { required: true, validator: equalToPassword, trigger: "blur" },
                      { pattern: /(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9]).{8,20}/,
                       message: '新密码长度必须介于 8 和 20 之间,并且包含大写字母、小写字母、数字、特殊字符',  trigger: "blur"
                      }
                    ]
                }
        }
    },
  mounted() {
    // 先清除token,防止回退后能直接登录,从而绕过强制重置密码的逻辑
    //setToken('');
    // 设置标志位,其他页面拿到这个值后不再向后端发送请求
    //localStorage.setItem("res_code", 1001);
    // 获取当前链接的参数
    const params = this.$route.query;
    this.resetForm.sign = params.sign;
    this.resetForm.username = params.username;
    this.token = params.token;
  },
  methods: {
    getFlag(){
    		this.flag = !this.flag;
    		this.flagType = this.flag?'text':'password'
		},
		getoldFlag(){
			this.oldflag = !this.oldflag;
			this.oldflagType = this.oldflag?'text':'password'
		},
		getreFlag(){
			this.reflag = !this.reflag;
			this.reflagType = this.reflag?'text':'password'
		},
    closeWin() {
          this.resetForm={
            username: "",
            oldPassword: "",
            newPassword: "",
            confirmPassword: "",
            code: "",
            sign: "",
            uuid: ""
          },
          this.$emit('closeWin');

          //删除登录成功设置的token
          //localStorage.removeItem("reset_token");
          localStorage.removeItem("res_code");
          localStorage.removeItem("res_sign");
          //清除token,强制登录
          setToken("")
          // 跳转到登录页
          //this.$router.push("/authentication/FullLogin");
          this.$router.push({ path: "/fulllogin" }).catch(() => {});
      },
    submitForm(){
      this.$refs.resetForm.validate(valid => {
        if (valid) {
          this.loading = true;
          resetUserProfilePwd(this.resetForm).then(response => {
            if(response.code=='200') {
              MessageBox.confirm('修改成功,新密码是:' + this.resetForm.newPassword, '系统提示', {
                    confirmButtonText: '重新登录',
                    showCancelButton: false, // 关闭取消按钮
                    //cancelButtonText: '取消',
                    type: 'warning'
                  }
              ).then(() => {
                this.closeWin()
              }).catch(() => {

              });
            }else{
              this.$message.success("修改失败" );
            }
          }).catch(() => {
            this.loading = false;
          })
        }
      });
		}
    }
};
</script>

三、重点:增加守卫路由

使用Vue的路由守卫来拦截密码过期未修改的用户访问系统的特定页面。在用户尝试访问系统的任何页面时,检查用户的密码过期状态,如果用户未修改,则直接显示强制改密页面。

在router.js中增加beforeEach,根据密码状态过滤访问页面,防止用户绕过强制改密页面。

javascript 复制代码
router.beforeEach((to, from, next) => {
    const token = getToken();
    const res_code = localStorage.getItem("res_code");
    const res_sign = localStorage.getItem("res_sign");
    const username = store.state.user.name
    if(token){
        if(to.name!=='resetPwd' && res_code==='1001'){
           // 重定向到强制改密页面
            next({ path: '/resetPwd?' + 'sign=' + res_sign+ '&username=' + username}); 
        }
        else {
            next(); // 继续正常的路由
        }
    }else{
        next(); // 继续正常的路由
    }

});

四、参考文章

【Ruoyi管理后台】用户登录强制修改密码

五、致谢

最后感谢博主reui-CSDN博客,以及博主的答疑。

相关推荐
吕彬-前端4 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱7 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai16 分钟前
uniapp
前端·javascript·vue.js·uni-app
duration~29 分钟前
Maven随笔
java·maven
zmgst32 分钟前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD42 分钟前
前后端分离,Jackson,Long精度丢失
java
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
暗黑起源喵1 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong1 小时前
Java反射
java·开发语言·反射