security: harden admin password change and production session headers

This commit is contained in:
2026-02-07 21:37:55 +08:00
parent 7997a97a9a
commit 08864e51ba
26 changed files with 159 additions and 59 deletions

View File

@@ -5,8 +5,13 @@ export async function updateAdminUsername(newUsername) {
return data
}
export async function updateAdminPassword(newPassword) {
const { data } = await api.put('/admin/password', { new_password: newPassword })
export async function updateAdminPassword(payload = {}) {
const currentPassword = String(payload.currentPassword || '')
const newPassword = String(payload.newPassword || '')
const { data } = await api.put('/admin/password', {
current_password: currentPassword,
new_password: newPassword,
})
return data
}
@@ -14,4 +19,3 @@ export async function logout() {
const { data } = await api.post('/logout')
return data
}

View File

@@ -5,7 +5,9 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { logout, updateAdminPassword, updateAdminUsername } from '../api/admin'
const username = ref('')
const currentPassword = ref('')
const password = ref('')
const confirmPassword = ref('')
const submitting = ref(false)
function validateStrongPassword(value) {
@@ -57,17 +59,31 @@ async function saveUsername() {
}
async function savePassword() {
const currentValue = currentPassword.value
const value = password.value
const confirmValue = confirmPassword.value
if (!currentValue) {
ElMessage.error('请输入当前密码')
return
}
if (!value) {
ElMessage.error('请输入新密码')
return
}
const check = validateStrongPassword(value)
if (!check.ok) {
ElMessage.error(check.message)
return
}
if (value !== confirmValue) {
ElMessage.error('两次输入的新密码不一致')
return
}
try {
await ElMessageBox.confirm('确定修改管理员密码吗?修改后需要重新登录。', '修改密码', {
confirmButtonText: '确认修改',
@@ -80,9 +96,11 @@ async function savePassword() {
submitting.value = true
try {
await updateAdminPassword(value)
await updateAdminPassword({ currentPassword: currentValue, newPassword: value })
ElMessage.success('密码修改成功,请重新登录')
currentPassword.value = ''
password.value = ''
confirmPassword.value = ''
setTimeout(relogin, 1200)
} catch {
// handled by interceptor
@@ -112,6 +130,16 @@ async function savePassword() {
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
<h3 class="section-title">修改管理员密码</h3>
<el-form label-width="120px">
<el-form-item label="当前密码">
<el-input
v-model="currentPassword"
type="password"
show-password
placeholder="输入当前密码"
:disabled="submitting"
/>
</el-form-item>
<el-form-item label="新密码">
<el-input
v-model="password"
@@ -121,6 +149,16 @@ async function savePassword() {
:disabled="submitting"
/>
</el-form-item>
<el-form-item label="确认新密码">
<el-input
v-model="confirmPassword"
type="password"
show-password
placeholder="再次输入新密码"
:disabled="submitting"
/>
</el-form-item>
</el-form>
<el-button type="primary" :loading="submitting" @click="savePassword">保存密码</el-button>
<div class="help">建议使用更强密码至少8位且包含字母与数字</div>