Forráskód Böngészése

用户密码支持自定义配置规则

RuoYi 1 hónapja
szülő
commit
f118c7d24f

+ 2 - 0
src/store/modules/user.js

@@ -1,4 +1,5 @@
 import router from '@/router'
+import cache from '@/plugins/cache'
 import { ElMessageBox, } from 'element-plus'
 import { login, logout, getInfo } from '@/api/login'
 import { getToken, setToken, removeToken } from '@/utils/auth'
@@ -55,6 +56,7 @@ const useUserStore = defineStore(
             this.name = user.userName
             this.nickName = user.nickName
             this.avatar = avatar
+            cache.session.set('pwrChrtype', res.pwdChrtype)
             /* 初始密码提示 */
             if(res.isDefaultModifyPwd) {
               ElMessageBox.confirm('您的密码还是初始密码,请修改密码!',  '安全提示', {  confirmButtonText: '确定',  cancelButtonText: '取消',  type: 'warning' }).then(() => {

+ 73 - 0
src/utils/passwordRule.js

@@ -0,0 +1,73 @@
+/**
+ * 密码强度规则
+ * 根据参数 chrtype 动态生成校验规则
+ *
+ * chrtype 说明:
+ *   0 - 任意字符(默认)
+ *   1 - 纯数字(0-9)
+ *   2 - 纯字母(a-z / A-Z)
+ *   3 - 字母 + 数字(必须同时包含)
+ *   4 - 字母 + 数字 + 特殊字符(必须同时包含,特殊字符:~!@#$%^&*()-=_+)
+ */
+
+import cache from '@/plugins/cache'
+
+// 密码限制类型
+const pwdChrType = ref(cache.session.get('pwrChrtype') || '0')
+
+// 各类型对应的正则、错误提示
+const PWD_RULES = {
+  '0': { pattern: /^[^<>"'|\\]+$/, message: '密码不能包含非法字符:< > " \' \\ |' },
+  '1': { pattern: /^[0-9]+$/, message: '密码只能为数字(0-9)' },
+  '2': { pattern: /^[a-zA-Z]+$/, message: '密码只能为英文字母(a-z、A-Z)' },
+  '3': { pattern: /^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$/, message: '密码必须同时包含字母和数字' },
+  '4': { pattern: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[~!@#$%^&*()\-=_+])[A-Za-z\d~!@#$%^&*()\-=_+]+$/, message: '密码必须同时包含字母、数字和特殊字符(~!@#$%^&*()-=_+)' }
+}
+
+export function usePasswordRule() {
+  // 默认密码校验
+  const pwdValidator = computed(() => {
+    const rule = PWD_RULES[pwdChrType.value] || PWD_RULES['0']
+    return [
+      { required: true, message: '密码不能为空', trigger: 'blur' },
+      { min: 6, max: 20, message: '密码长度必须介于 6 和 20 之间', trigger: 'blur' },
+      { pattern: rule.pattern, message: rule.message, trigger: 'blur' }
+    ]
+  })
+  // 校验prompt的inputValidator函数
+  const pwdPromptValidator = (value) => {
+    const rule = PWD_RULES['0']
+    if (!value || value.length < 6 || value.length > 20) {
+      return '密码长度必须介于 6 和 20 之间'
+    }
+    if (!rule.pattern.test(value)) {
+      return rule.message
+    }
+  }
+  // 个人中心密码校验
+  const infoPwdValidator = computed(() => {
+    const rule = PWD_RULES[pwdChrType.value] || PWD_RULES['0']
+    return [
+      { required: true, message: '新密码不能为空', trigger: 'blur' },
+      { min: 6, max: 20, message: '新密码长度必须介于 6 和 20 之间', trigger: 'blur' },
+      { pattern: rule.pattern, message: rule.message, trigger: 'blur' }
+    ]
+  })
+  // 注册页面密码校验
+  const registerPwdValidator = computed(() => {
+    const rule = PWD_RULES['0']
+    return [
+      { required: true, message: '请输入您的密码', trigger: 'blur' },
+      { min: 6, max: 20, message: '用户密码长度必须介于 6 和 20 之间', trigger: 'blur' },
+      { pattern: rule.pattern, message: rule.message, trigger: 'blur' }
+    ]
+  })
+
+  return {
+    pwdChrType,
+    pwdValidator,
+    infoPwdValidator,
+    pwdPromptValidator,
+    registerPwdValidator
+  }
+}

+ 3 - 6
src/views/register.vue

@@ -13,7 +13,7 @@
           <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
         </el-input>
       </el-form-item>
-      <el-form-item prop="password">
+      <el-form-item prop="password" :rules="registerPwdValidator">
         <el-input
           v-model="registerForm.password"
           type="password"
@@ -79,11 +79,13 @@
 import { ElMessageBox } from "element-plus"
 import { getCodeImg, register } from "@/api/login"
 import defaultSettings from '@/settings'
+import { usePasswordRule } from "@/utils/passwordRule"
 
 const title = import.meta.env.VITE_APP_TITLE
 const footerContent = defaultSettings.footerContent
 const router = useRouter()
 const { proxy } = getCurrentInstance()
+const { registerPwdValidator } = usePasswordRule()
 
 const registerForm = ref({
   username: "",
@@ -106,11 +108,6 @@ const registerRules = {
     { required: true, trigger: "blur", message: "请输入您的账号" },
     { min: 2, max: 20, message: "用户账号长度必须介于 2 和 20 之间", trigger: "blur" }
   ],
-  password: [
-    { required: true, trigger: "blur", message: "请输入您的密码" },
-    { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" },
-    { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
-  ],
   confirmPassword: [
     { required: true, trigger: "blur", message: "请再次输入您的密码" },
     { required: true, validator: equalToPassword, trigger: "blur" }

+ 5 - 10
src/views/system/user/index.vue

@@ -124,7 +124,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
+            <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password" :rules="pwdValidator">
               <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
             </el-form-item>
           </el-col>
@@ -188,10 +188,12 @@
 import TreePanel from "@/components/TreePanel"
 import ExcelImportDialog from "@/components/ExcelImportDialog"
 import UserViewDrawer from "./view"
+import { usePasswordRule } from "@/utils/passwordRule"
 import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect } from "@/api/system/user"
 
 const router = useRouter()
 const { proxy } = getCurrentInstance()
+const { pwdValidator, pwdPromptValidator } = usePasswordRule()
 const { sys_normal_disable, sys_user_sex } = useDict("sys_normal_disable", "sys_user_sex")
 
 const userList = ref([])
@@ -233,7 +235,6 @@ const data = reactive({
   rules: {
     userName: [{ required: true, message: "用户名称不能为空", trigger: "blur" }, { min: 2, max: 20, message: "用户名称长度必须介于 2 和 20 之间", trigger: "blur" }],
     nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
-    password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
     email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
     phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
   }
@@ -345,17 +346,11 @@ function handleAuthRole(row) {
 
 /** 重置密码按钮操作 */
 function handleResetPwd(row) {
-  proxy.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
+  proxy.$prompt(`请输入「${row.userName}」的新密码`, "重置密码", {
     confirmButtonText: "确定",
     cancelButtonText: "取消",
     closeOnClickModal: false,
-    inputPattern: /^.{5,20}$/,
-    inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
-    inputValidator: (value) => {
-      if (/<|>|"|'|\||\\/.test(value)) {
-        return "不能包含非法字符:< > \" ' \\\ |"
-      }
-    },
+    inputValidator: pwdPromptValidator
   }).then(({ value }) => {
     resetUserPwd(row.userId, value).then(() => {
       proxy.$modal.msgSuccess("修改成功,新密码是:" + value)

+ 15 - 14
src/views/system/user/profile/resetPwd.vue

@@ -1,25 +1,27 @@
 <template>
-   <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
-      <el-form-item label="旧密码" prop="oldPassword">
-         <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
-      </el-form-item>
-      <el-form-item label="新密码" prop="newPassword">
-         <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password />
-      </el-form-item>
-      <el-form-item label="确认密码" prop="confirmPassword">
-         <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
-      </el-form-item>
-      <el-form-item>
+  <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
+    <el-form-item label="旧密码" prop="oldPassword">
+      <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
+    </el-form-item>
+    <el-form-item label="新密码" prop="newPassword" :rules="infoPwdValidator">
+      <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password />
+    </el-form-item>
+    <el-form-item label="确认密码" prop="confirmPassword">
+      <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password />
+    </el-form-item>
+    <el-form-item>
       <el-button type="primary" @click="submit">保存</el-button>
       <el-button type="danger" @click="close">关闭</el-button>
-      </el-form-item>
-   </el-form>
+    </el-form-item>
+  </el-form>
 </template>
 
 <script setup>
+import { usePasswordRule } from "@/utils/passwordRule"
 import { updateUserPwd } from "@/api/system/user"
 
 const { proxy } = getCurrentInstance()
+const { infoPwdValidator } = usePasswordRule()
 
 const user = reactive({
   oldPassword: undefined,
@@ -37,7 +39,6 @@ const equalToPassword = (rule, value, callback) => {
 
 const rules = ref({
   oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
-  newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
   confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
 })