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

This commit is contained in:
RuoYi
2026-04-17 14:47:43 +08:00
parent 377dc71417
commit 3979713783
7 changed files with 126 additions and 52 deletions

View File

@@ -189,11 +189,18 @@ public class SysUserController extends BaseController
ajax.put("user", user);
ajax.put("roles", roles);
ajax.put("permissions", permissions);
ajax.put("pwdChrtype", getSysAccountChrtype());
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
return ajax;
}
// 获取用户密码自定义配置规则
public String getSysAccountChrtype()
{
return Convert.toStr(configService.selectConfigByKey("sys.account.chrtype"), "0");
}
// 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate)
{

View File

@@ -1,5 +1,6 @@
import store from '@/store'
import router from '@/router'
import cache from '@/plugins/cache'
import { MessageBox, } from 'element-ui'
import { login, logout, getInfo, refreshToken } from '@/api/login'
import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth'
@@ -82,6 +83,7 @@ const user = {
commit('SET_NAME', user.userName)
commit('SET_NICK_NAME', user.nickName)
commit('SET_AVATAR', avatar)
cache.session.set('pwrChrtype', res.pwdChrtype)
/* 初始密码提示 */
if(res.isDefaultModifyPwd) {
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {

View File

@@ -0,0 +1,71 @@
/**
* 密码强度规则
* 根据参数 chrtype 动态生成校验规则
*
* chrtype 说明:
* 0 - 任意字符(默认)
* 1 - 纯数字0-9
* 2 - 纯字母a-z / A-Z
* 3 - 字母 + 数字(必须同时包含)
* 4 - 字母 + 数字 + 特殊字符(必须同时包含,特殊字符:~!@#$%^&*()-=_+
*/
import cache from '@/plugins/cache'
// 各类型对应的正则、错误提示
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 default {
data() {
return {
// 密码限制类型
pwdChrType: cache.session.get('pwrChrtype') || '0'
}
},
computed: {
// 默认密码校验
pwdValidator() {
const rule = PWD_RULES[this.pwdChrType] || 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函数
pwdPromptValidator() {
const rule = PWD_RULES['0']
return (value) => {
if (!value || value.length < 6 || value.length > 20) {
return '密码长度必须介于 6 和 20 之间'
}
if (!rule.pattern.test(value)) {
return rule.message
}
}
},
// 个人中心密码校验
infoPwdValidator() {
const rule = PWD_RULES[this.pwdChrType] || 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' }
]
},
// 注册页面密码校验
registerPwdValidator() {
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' }
]
}
}
}

View File

@@ -7,7 +7,7 @@
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
</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"
@@ -68,18 +68,12 @@
<script>
import { getCodeImg, register } from "@/api/login"
import passwordRule from "@/utils/passwordRule"
import defaultSettings from '@/settings'
export default {
name: "Register",
mixins: [passwordRule],
data() {
const equalToPassword = (rule, value, callback) => {
if (this.registerForm.password !== value) {
callback(new Error("两次输入的密码不一致"))
} else {
callback()
}
}
return {
title: process.env.VUE_APP_TITLE,
footerContent: defaultSettings.footerContent,
@@ -91,24 +85,31 @@ export default {
code: "",
uuid: ""
},
registerRules: {
loading: false,
captchaEnabled: true
}
},
computed: {
registerRules() {
return {
username: [
{ 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" }
{ required: true, message: "请再次输入您的密码", trigger: "blur" },
{
validator: (rule, value, callback) => {
if (this.registerForm.password !== value) {
callback(new Error("两次输入的密码不一致"))
} else {
callback()
}
}, trigger: "blur"
}
],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
},
loading: false,
captchaEnabled: true
}
}
},
created() {

View File

@@ -116,7 +116,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>
@@ -181,9 +181,11 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import TreePanel from "@/components/TreePanel"
import ExcelImportDialog from "@/components/ExcelImportDialog"
import UserViewDrawer from "./view"
import passwordRule from "@/utils/passwordRule"
export default {
name: "User",
mixins: [passwordRule],
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect, TreePanel, ExcelImportDialog, UserViewDrawer },
data() {
@@ -248,11 +250,6 @@ export default {
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",
@@ -405,17 +402,11 @@ export default {
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
this.$prompt(`请输入「${row.userName}的新密码`, "重置密码", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
inputValidator: this.pwdPromptValidator
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(() => {
this.$modal.msgSuccess("修改成功,新密码是:" + value)

View File

@@ -1,9 +1,9 @@
<template>
<el-form ref="form" :model="user" :rules="rules" label-width="80px">
<el-form ref="form" :model="user" :rules="formRules" 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-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">
@@ -18,35 +18,36 @@
<script>
import { updateUserPwd } from "@/api/system/user"
import passwordRule from "@/utils/passwordRule"
export default {
mixins: [passwordRule],
data() {
const equalToPassword = (rule, value, callback) => {
if (this.user.newPassword !== value) {
callback(new Error("两次输入的密码不一致"))
} else {
callback()
}
}
return {
user: {
oldPassword: undefined,
newPassword: undefined,
confirmPassword: undefined
},
// 表单校验
rules: {
}
}
},
computed: {
formRules() {
return {
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" }
{
validator: (rule, value, callback) => {
if (this.user.newPassword !== value) {
callback(new Error("两次输入的密码不一致"))
} else {
callback()
}
}, trigger: "blur"
}
]
}
}

View File

@@ -552,6 +552,7 @@ insert into sys_config values(4, '账号自助-是否开启用户注册功能',
insert into sys_config values(5, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制多个匹配项以;分隔,支持匹配(*通配、网段)');
insert into sys_config values(6, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '1', 'Y', 'admin', sysdate(), '', null, '0初始密码修改策略关闭没有任何提示1提醒用户如果未修改初始密码则在登录时就会提醒修改密码对话框');
insert into sys_config values(7, '用户管理-账号密码更新周期', 'sys.account.passwordValidateDays', '0', 'Y', 'admin', sysdate(), '', null, '密码更新周期填写数字数据初始化值为0不限制若修改必须为大于0小于365的正整数如果超过这个周期登录系统时则在登录时就会提醒修改密码对话框');
insert into sys_config values(8, '用户管理-密码字符范围', 'sys.account.chrtype', '0', 'Y', 'admin', sysdate(), '', null, '默认任意字符范围0任意密码可以输入任意字符1数字密码只能为0-9数字2英文字母密码只能为a-z和A-Z字母3字母和数字密码必须包含字母数字,4字母数字和特殊字符目前支持的特殊字符包括~!@#$%^&*()-=_+');
-- ----------------------------