forked from integrated_whb/integrated_whb_vue
				
			feat(security): 修改默认密码并增加密码强度验证
- 将默认密码从 "Aa@123456" 修改为 "Jtys@123456" - 在用户信息页面添加修改密码对话框,增加密码强度验证 - 更新登录逻辑,传递密码类型和令牌到首页 - 修改密码后自动登出并重定向到登录页面dev
							parent
							
								
									c28fec0270
								
							
						
					
					
						commit
						4f0a07f2fc
					
				|  | @ -23,9 +23,6 @@ | |||
|           autocomplete="off" | ||||
|         /> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="姓名" prop="NAME"> | ||||
|         <el-input v-model="form.NAME" placeholder="这里输入姓名..." /> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="邮箱" prop="EMAIL"> | ||||
|         <el-input v-model="form.EMAIL" placeholder="这里输入邮箱..." /> | ||||
|       </el-form-item> | ||||
|  | @ -46,13 +43,14 @@ | |||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { getVerifyDuplicateEmail, setUserInfo } from "@/request/api.js"; | ||||
| import {getVerifyDuplicateEmail, logout, setUserInfo} from "@/request/api.js"; | ||||
| import { useVModels } from "@vueuse/core"; | ||||
| import { debounce } from "throttle-debounce"; | ||||
| import useFormValidate from "@/assets/js/useFormValidate.js"; | ||||
| import { ElMessage } from "element-plus"; | ||||
| import { useUserStore } from "@/pinia/user.js"; | ||||
| import { ref } from "vue"; | ||||
| import {useRouter} from "vue-router"; | ||||
| 
 | ||||
| const userStore = useUserStore(); | ||||
| const props = defineProps({ | ||||
|  | @ -69,6 +67,7 @@ const props = defineProps({ | |||
| }); | ||||
| const emits = defineEmits(["update:visible", "update:form", "get-data"]); | ||||
| const { visible, form } = useVModels(props, emits); | ||||
| const router = useRouter(); | ||||
| const formRef = ref(null); | ||||
| const validatePass = (rule, value, callback) => { | ||||
|   if (value) { | ||||
|  | @ -106,7 +105,6 @@ const validateEmail = async (rule, value, callback) => { | |||
|   } else callback(); | ||||
| }; | ||||
| const rules = { | ||||
|   NAME: [{ required: true, message: "姓名不能为空", trigger: "blur" }], | ||||
|   EMAIL: [ | ||||
|     { required: false, message: "请输入邮箱", trigger: "blur" }, | ||||
|     { | ||||
|  | @ -133,12 +131,17 @@ const fnSubmit = debounce( | |||
|       ...form.value, | ||||
|       PASSWORD: form.value.newpwd, | ||||
|     }); | ||||
|     fnClose(); | ||||
|     ElMessage.success("修改成功"); | ||||
|     await fnSignOut(); | ||||
|     emits("get-data"); | ||||
|   }, | ||||
|   { atBegin: true } | ||||
| ); | ||||
| const fnSignOut = async () => { | ||||
|   await logout(); | ||||
|   userStore.$reset(); | ||||
|   await router.replace("/login"); | ||||
| }; | ||||
| const fnClose = () => { | ||||
|   formRef.value.resetFields(); | ||||
|   visible.value = false; | ||||
|  |  | |||
|  | @ -615,7 +615,7 @@ const fnGetData = async () => { | |||
|   if (!USER_ID) return; | ||||
|   const resData = await getUserView({ USER_ID }); | ||||
|   const form = resData.pd; | ||||
|   form.PASSWORD = "Aa@123456"; | ||||
|   form.PASSWORD = "Jtys@123456"; | ||||
|   form.periodStr = resData.periodStr; | ||||
|   form.ISSTUDENT = resData.pd.ISSTUDENT.toString(); | ||||
|   if (form.USERAVATARURL_CONVERT) | ||||
|  |  | |||
|  | @ -261,7 +261,7 @@ onBeforeRouteUpdate((to) => { | |||
| const fnResetPassword = debounce( | ||||
|   1000, | ||||
|   async (USER_ID, NAME) => { | ||||
|     await ElMessageBox.confirm(`是否将【${NAME}】重置密码为Aa@123456?`, { | ||||
|     await ElMessageBox.confirm(`是否将【${NAME}】重置密码为Jtys@123456?`, { | ||||
|       type: "warning", | ||||
|     }); | ||||
|     await setUserResetPassword({ USER_ID }); | ||||
|  |  | |||
|  | @ -1078,7 +1078,7 @@ const fnGetData = async () => { | |||
|   if (!USER_ID) return; | ||||
|   const resData = await getUserView({ USER_ID }); | ||||
|   const form = resData.pd; | ||||
|   form.PASSWORD = "Aa@123456"; | ||||
|   form.PASSWORD = "Jtys@123456"; | ||||
|   form.periodStr = resData.periodStr; | ||||
|   form.ISSTUDENT = resData.pd.ISSTUDENT.toString(); | ||||
|   if (form.USERAVATARURL_CONVERT) | ||||
|  |  | |||
|  | @ -980,7 +980,7 @@ const fnGetData = async (USER_ID) => { | |||
|   if (!USER_ID) return; | ||||
|   const resData = await getPractitionerForEdit({ USER_ID }); | ||||
|   const form = resData.pd; | ||||
|   form.PASSWORD = "Aa@123456"; | ||||
|   form.PASSWORD = "Jtys@123456"; | ||||
|   form.periodStr = resData.periodStr; | ||||
|   form.ISSTUDENT = resData.pd.ISSTUDENT.toString(); | ||||
|   if (form.USERAVATARURL_CONVERT) | ||||
|  |  | |||
|  | @ -952,7 +952,7 @@ const fnGetData = async () => { | |||
|   if (!USER_ID) return; | ||||
|   const resData = await getPractitionerForEdit({ USER_ID }); | ||||
|   const form = resData.pd; | ||||
|   form.PASSWORD = "Aa@123456"; | ||||
|   form.PASSWORD = "Jtys@123456"; | ||||
|   form.periodStr = resData.periodStr; | ||||
|   form.ISSTUDENT = resData.pd.ISSTUDENT.toString(); | ||||
|   if (form.USERAVATARURL_CONVERT) { | ||||
|  |  | |||
|  | @ -28,6 +28,48 @@ | |||
|         <waybill /> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|     <el-dialog | ||||
|       v-model="dialogFormEdit" | ||||
|       :before-close="handleClose" | ||||
|       :append-to-body="true" | ||||
|       title="登录的密码强度为弱,请修改密码!" | ||||
|       width="600px" | ||||
|     > | ||||
|       <div style="padding: 0 40px"> | ||||
|         <el-form | ||||
|           ref="formRef" | ||||
|           :model="form" | ||||
|           :rules="rules" | ||||
|           status-icon | ||||
|           label-width="100px" | ||||
|         > | ||||
|           <el-form-item label="用户名"> | ||||
|             <el-input | ||||
|               v-model="form.USERNAME" | ||||
|               disabled | ||||
|               placeholder="默认用户手机号码..." | ||||
|             /> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="新密码:" prop="newpwd"> | ||||
|             <el-input | ||||
|               v-model="form.newpwd" | ||||
|               type="password" | ||||
|               auto-complete="off" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="确认密码:" prop="newpassword1"> | ||||
|             <el-input | ||||
|               v-model="form.newpassword1" | ||||
|               type="password" | ||||
|               auto-complete="off" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|         <div style="text-align: center; margin-top: 30px"> | ||||
|           <el-button type="primary" @click="editUser">确认修改</el-button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -41,6 +83,92 @@ import doublePrevention from "./components/doublePrevention.vue"; | |||
| import info from "./components/info.vue"; | ||||
| import statistics from "./components/statistics.vue"; | ||||
| import waybill from "./components/waybill.vue"; | ||||
| import { debounce } from "throttle-debounce"; | ||||
| import { logout, setUserInfo } from "@/request/api.js"; | ||||
| import { ElMessage } from "element-plus"; | ||||
| import { useUserStore } from "@/pinia/user.js"; | ||||
| import { useRoute, useRouter } from "vue-router"; | ||||
| import { ref, onMounted } from "vue"; | ||||
| import useFormValidate from "@/assets/js/useFormValidate.js"; | ||||
| const userStore = useUserStore(); | ||||
| 
 | ||||
| const form = ref({ | ||||
|   USERNAME: userStore.getUserInfo.USERNAME, | ||||
|   newpwd: "", | ||||
|   newpassword1: "", | ||||
| }); | ||||
| const formRef = ref(null); | ||||
| const router = useRouter(); | ||||
| const route = useRoute(); | ||||
| const passwordType = route.query.passwordType; | ||||
| const dialogFormEdit = ref(false); | ||||
| 
 | ||||
| onMounted(() => { | ||||
|   // 检查 passwordType 是否为 '0'(路由参数是字符串类型) | ||||
|   if (passwordType === "0") { | ||||
|     dialogFormEdit.value = true; | ||||
|     console.log(dialogFormEdit.value); | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| const validatePass = (rule, value, callback) => { | ||||
|   if (value) { | ||||
|     const reg1 = | ||||
|       /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[~!@#$%^&*.])[\da-zA-Z~!@#$%^&*.]{8,}$/; | ||||
|     if (!reg1.test(value)) { | ||||
|       callback( | ||||
|         new Error("密码必须是8位以上、必须包含大小写字母、数字、特殊符号") | ||||
|       ); | ||||
|     } else { | ||||
|       callback(); | ||||
|     } | ||||
|   } else { | ||||
|     callback(); | ||||
|   } | ||||
| }; | ||||
| const validatePass2 = (rule, value, callback) => { | ||||
|   if (form.value.newpwd && !value) { | ||||
|     callback(new Error("请再次输入新密码")); | ||||
|   } else if (form.value.newpwd && value && value !== form.value.newpwd) { | ||||
|     callback(new Error("两次输入密码不一致!")); | ||||
|   } else callback(); | ||||
| }; | ||||
| 
 | ||||
| const rules = { | ||||
|   newpwd: [ | ||||
|     { required: false, message: "请输入新密码", trigger: "blur" }, | ||||
|     { required: true, validator: validatePass, trigger: "blur" }, | ||||
|   ], | ||||
|   newpassword1: [ | ||||
|     { required: false, validator: validatePass2, trigger: "blur" }, | ||||
|   ], | ||||
| }; | ||||
| 
 | ||||
| const editUser = debounce( | ||||
|   1000, | ||||
|   async () => { | ||||
|     await useFormValidate(formRef); | ||||
|     await setUserInfo({ | ||||
|       USER_ID: userStore.getUserInfo.USER_ID, | ||||
|       OPERATIONTYPE: "1", | ||||
|       ...form.value, | ||||
|       PASSWORD: form.value.newpwd, | ||||
|     }); | ||||
|     ElMessage.success("修改成功"); | ||||
|     await fnSignOut(); | ||||
|   }, | ||||
|   { atBegin: true } | ||||
| ); | ||||
| const fnSignOut = async () => { | ||||
|   await logout(); | ||||
|   userStore.$reset(); | ||||
|   await router.replace("/login"); | ||||
| }; | ||||
| const handleClose = (done) => { | ||||
|   if (!dialogFormEdit.value) { | ||||
|     done(); | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
|  |  | |||
|  | @ -143,11 +143,18 @@ const fnSubmitLogin = async () => { | |||
|     KEYDATA, | ||||
|     SOURCE: 1, | ||||
|   }); | ||||
|   console.log(resData,'123') | ||||
|   await userStore.setUserInfo({ | ||||
|     ...userStore.getUserInfo, | ||||
|     ...resData, | ||||
|   }); | ||||
|   await router.replace("/index"); | ||||
|   await router.replace({ | ||||
|     path: "/index", | ||||
|     query: { | ||||
|       passwordType: resData.passwordType, | ||||
|       token: resData.token, // 传递令牌 | ||||
|     }, | ||||
|   }); | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue