mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-26 02:31:20 +08:00
feat: 更新密码功能增强,添加新密码强度验证和旧密码检查
This commit is contained in:
parent
5499b5fbc9
commit
d3013e32e1
@ -14,8 +14,9 @@ const ChangePasswordCard = () => {
|
||||
const {
|
||||
control,
|
||||
handleSubmit: handleWebuiSubmit,
|
||||
formState: { isSubmitting },
|
||||
reset
|
||||
formState: { isSubmitting, errors },
|
||||
reset,
|
||||
watch
|
||||
} = useForm<{
|
||||
oldToken: string
|
||||
newToken: string
|
||||
@ -29,6 +30,9 @@ const ChangePasswordCard = () => {
|
||||
const navigate = useNavigate()
|
||||
const [_, setToken] = useLocalStorage(key.token, '')
|
||||
|
||||
// 监听旧密码的值
|
||||
const oldTokenValue = watch('oldToken')
|
||||
|
||||
const onSubmit = handleWebuiSubmit(async (data) => {
|
||||
try {
|
||||
// 使用正常密码更新流程
|
||||
@ -51,12 +55,24 @@ const ChangePasswordCard = () => {
|
||||
<Controller
|
||||
control={control}
|
||||
name="oldToken"
|
||||
rules={{
|
||||
required: '旧密码不能为空',
|
||||
validate: (value) => {
|
||||
if (!value || value.trim().length === 0) {
|
||||
return '旧密码不能为空'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
{...field}
|
||||
label="旧密码"
|
||||
placeholder="请输入旧密码"
|
||||
type="password"
|
||||
isRequired
|
||||
isInvalid={!!errors.oldToken}
|
||||
errorMessage={errors.oldToken?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@ -64,12 +80,42 @@ const ChangePasswordCard = () => {
|
||||
<Controller
|
||||
control={control}
|
||||
name="newToken"
|
||||
rules={{
|
||||
required: '新密码不能为空',
|
||||
minLength: {
|
||||
value: 6,
|
||||
message: '新密码至少需要6个字符'
|
||||
},
|
||||
validate: (value) => {
|
||||
if (!value || value.trim().length === 0) {
|
||||
return '新密码不能为空'
|
||||
}
|
||||
if (value.trim().length !== value.length) {
|
||||
return '新密码不能包含前后空格'
|
||||
}
|
||||
if (value === oldTokenValue) {
|
||||
return '新密码不能与旧密码相同'
|
||||
}
|
||||
// 检查是否包含字母
|
||||
if (!/[a-zA-Z]/.test(value)) {
|
||||
return '新密码必须包含字母'
|
||||
}
|
||||
// 检查是否包含数字
|
||||
if (!/[0-9]/.test(value)) {
|
||||
return '新密码必须包含数字'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
{...field}
|
||||
label="新密码"
|
||||
placeholder="请输入新密码"
|
||||
placeholder="至少6位,包含字母和数字"
|
||||
type="password"
|
||||
isRequired
|
||||
isInvalid={!!errors.newToken}
|
||||
errorMessage={errors.newToken?.message}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@ -92,16 +92,36 @@ export const checkHandler: RequestHandler = async (req, res) => {
|
||||
|
||||
// 修改密码(token)
|
||||
export const UpdateTokenHandler: RequestHandler = async (req, res) => {
|
||||
const { oldToken, newToken, fromDefault } = req.body;
|
||||
const { oldToken, newToken } = req.body;
|
||||
const authorization = req.headers.authorization;
|
||||
|
||||
if (isEmpty(newToken)) {
|
||||
return sendError(res, 'newToken is empty');
|
||||
}
|
||||
|
||||
// 如果不是从默认密码更新,则需要验证旧密码
|
||||
if (!fromDefault && isEmpty(oldToken)) {
|
||||
return sendError(res, 'oldToken is required when not updating from default password');
|
||||
// 强制要求旧密码
|
||||
if (isEmpty(oldToken)) {
|
||||
return sendError(res, 'oldToken is required');
|
||||
}
|
||||
|
||||
// 检查新旧密码是否相同
|
||||
if (oldToken === newToken) {
|
||||
return sendError(res, '新密码不能与旧密码相同');
|
||||
}
|
||||
|
||||
// 检查新密码强度
|
||||
if (newToken.length < 6) {
|
||||
return sendError(res, '新密码至少需要6个字符');
|
||||
}
|
||||
|
||||
// 检查是否包含字母
|
||||
if (!/[a-zA-Z]/.test(newToken)) {
|
||||
return sendError(res, '新密码必须包含字母');
|
||||
}
|
||||
|
||||
// 检查是否包含数字
|
||||
if (!/[0-9]/.test(newToken)) {
|
||||
return sendError(res, '新密码必须包含数字');
|
||||
}
|
||||
|
||||
try {
|
||||
@ -112,29 +132,18 @@ export const UpdateTokenHandler: RequestHandler = async (req, res) => {
|
||||
AuthHelper.revokeCredential(Credential);
|
||||
}
|
||||
|
||||
if (fromDefault) {
|
||||
// 从默认密码更新,直接设置新密码
|
||||
const currentConfig = await WebUiConfig.GetWebUIConfig();
|
||||
if (!currentConfig.defaultToken) {
|
||||
return sendError(res, 'Current password is not default password');
|
||||
}
|
||||
await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false });
|
||||
// 更新内存中的缓存token,使新密码立即生效
|
||||
setInitialWebUiToken(newToken);
|
||||
} else {
|
||||
// 正常的密码更新流程 - 使用启动时缓存的token进行验证
|
||||
const initialToken = getInitialWebUiToken();
|
||||
if (!initialToken) {
|
||||
return sendError(res, 'Server token not initialized');
|
||||
}
|
||||
if (initialToken !== oldToken) {
|
||||
return sendError(res, '旧 token 不匹配');
|
||||
}
|
||||
// 直接更新配置文件中的token,不需要通过WebUiConfig.UpdateToken方法
|
||||
await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false });
|
||||
// 更新内存中的缓存token,使新密码立即生效
|
||||
setInitialWebUiToken(newToken);
|
||||
// 使用启动时缓存的token进行验证
|
||||
const initialToken = getInitialWebUiToken();
|
||||
if (!initialToken) {
|
||||
return sendError(res, 'Server token not initialized');
|
||||
}
|
||||
if (initialToken !== oldToken) {
|
||||
return sendError(res, '旧 token 不匹配');
|
||||
}
|
||||
// 直接更新配置文件中的token,不需要通过WebUiConfig.UpdateToken方法
|
||||
await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false });
|
||||
// 更新内存中的缓存token,使新密码立即生效
|
||||
setInitialWebUiToken(newToken);
|
||||
|
||||
return sendSuccess(res, 'Token updated successfully');
|
||||
} catch (e: any) {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
|
||||
import {
|
||||
CheckDefaultTokenHandler,
|
||||
checkHandler,
|
||||
LoginHandler,
|
||||
LogoutHandler,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user