fix: 修复多项后端缺陷并加固安全与限流

- 修正 AI 会话表初始化及异步数据库 URI 处理
- 新增全局 API 与 WS 聊天限流,健康检查豁免
- 修复忘记密码接口防用户枚举与参数校验
- 修复 SSE 推送数据重复编码问题
- 修复 Cron 表达式 Quartz 问号兼容
- 修复存储模块权限标识前缀
- 新增过期日志清理与任务错误中文提示
This commit is contained in:
zhangtao
2026-09-07 00:08:00 +08:00
parent 30dfc7097b
commit a8d29d4ab4
59 changed files with 989 additions and 891 deletions
+1 -2
View File
@@ -169,10 +169,9 @@ const UserAPI = {
export default UserAPI
/* 忘记密码表单(与后端 UserForgetPasswordSchema 一致,confirmPassword 为前端校验字段不提交) */
/* 忘记密码申请(与后端 UserForgetPasswordSchema 一致:仅用户名,后端不会直接改密) */
export interface ForgetPasswordForm {
username: string
new_password: string
}
/* 注册表单 */
+3 -35
View File
@@ -17,8 +17,6 @@ const submitting = ref(false)
const forgetFormRef = ref()
const forgetForm = reactive({
username: '',
new_password: '',
confirmPassword: '',
})
/** 与后端 UserForgetPasswordSchema 一致:字母开头,3-32 位,仅允许字母、数字、_ . - */
@@ -29,25 +27,15 @@ const forgetSchema: FormSchema = {
validate: (model) => {
const errors: Array<{ path: Array<string | number>, message: string }> = []
const username = String(model.username ?? '').trim()
const password = String(model.new_password ?? '')
const confirmPassword = String(model.confirmPassword ?? '')
if (!username)
errors.push({ path: ['username'], message: t('common.form.usernameRequired') })
else if (!USERNAME_REG.test(username))
errors.push({ path: ['username'], message: t('common.form.usernameFormat') })
if (!password)
errors.push({ path: ['new_password'], message: t('common.form.newPasswordRequired') })
else if (password.length < 6)
errors.push({ path: ['new_password'], message: t('common.form.passwordLength') })
if (!confirmPassword)
errors.push({ path: ['confirmPassword'], message: t('common.form.confirmNewRequired') })
else if (confirmPassword !== password)
errors.push({ path: ['confirmPassword'], message: t('common.form.mismatch') })
return errors
},
}
/** 重置密码成功后记住用户名,回登录页由用户用新密码登录 */
/** 提交忘记密码申请:后端不会直接改密,成功后提示联系管理员 */
async function handleSubmit() {
if (submitting.value)
return
@@ -58,13 +46,13 @@ async function handleSubmit() {
const username = forgetForm.username.trim()
submitting.value = true
try {
await UserAPI.forgetPassword({ username, new_password: forgetForm.new_password })
await UserAPI.forgetPassword({ username })
Storage.set(REMEMBER_ME_KEY, { username, remember: true })
toast.success(t('forget.success'))
uni.reLaunch({ url: '/pages/login/index' })
}
catch {
// http 层已统一错误提示(如用户不存在)
// http 层已统一错误提示
}
finally {
submitting.value = false
@@ -94,26 +82,6 @@ function goLogin() {
prefix-icon="user"
/>
</wd-form-item>
<wd-form-item prop="new_password" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="forgetForm.new_password"
:placeholder="t('common.form.newPasswordPlaceholder')"
show-password
clearable
:compact="false"
prefix-icon="lock"
/>
</wd-form-item>
<wd-form-item prop="confirmPassword" custom-style="margin-bottom: 14rpx; padding-left: 0; padding-right: 0;">
<wd-input
v-model="forgetForm.confirmPassword"
:placeholder="t('common.form.confirmNewPlaceholder')"
show-password
clearable
:compact="false"
prefix-icon="lock"
/>
</wd-form-item>
</wd-form>
<wd-button type="primary" round block :loading="submitting" @click="handleSubmit">
{{ submitting ? t('forget.submitting') : t('forget.submit') }}