fix: harden cloud storage security

This commit is contained in:
237899745
2026-06-13 18:45:12 +08:00
parent 7943b04ee2
commit bb6ad01018
28 changed files with 2229 additions and 996 deletions

View File

@@ -292,8 +292,8 @@
<div class="form-group">
<label class="form-label">新密码</label>
<input type="password" id="password" class="form-input"
placeholder="请输入新密码" required minlength="6">
<div class="password-hint">密码长度至少6位</div>
placeholder="请输入新密码" required minlength="8" maxlength="128">
<div class="password-hint">密码长度8-128位且包含字母、数字、特殊字符中的至少两种</div>
</div>
<div class="form-group">
@@ -347,6 +347,28 @@
return url.searchParams.get(name);
}
function getCookie(name) {
const prefix = `${name}=`;
const row = document.cookie
.split('; ')
.find(item => item.startsWith(prefix));
return row ? decodeURIComponent(row.substring(prefix.length)) : '';
}
async function ensureCsrfToken() {
let token = getCookie('csrf_token');
if (token) return token;
try {
const res = await fetch('/api/csrf-token', { credentials: 'include' });
const data = await res.json().catch(() => ({}));
token = data.csrfToken || data.token || getCookie('csrf_token');
} catch (error) {
console.warn('[CSRF] 获取 token 失败:', error.message);
}
return token || getCookie('csrf_token');
}
// 显示指定区块
function showSection(id) {
['loading', 'error', 'form', 'success'].forEach(s => {
@@ -363,6 +385,35 @@
alert.classList.remove('hidden');
}
function validateAccountPassword(password) {
const value = String(password || '');
if (value.length < 8) {
return { valid: false, message: '密码至少8个字符' };
}
if (value.length > 128) {
return { valid: false, message: '密码不能超过128个字符' };
}
const typeCount = [
/[a-zA-Z]/.test(value),
/[0-9]/.test(value),
/[!@#$%^&*(),.?":{}|<>_\-+=\[\]\\\/`~]/.test(value)
].filter(Boolean).length;
if (typeCount < 2) {
return { valid: false, message: '密码必须包含字母、数字、特殊字符中的至少两种' };
}
const weakPasswords = [
'password', '12345678', '123456789', 'qwerty123', 'admin123',
'letmein', 'welcome', 'monkey', 'dragon', 'master'
];
if (weakPasswords.includes(value.toLowerCase())) {
return { valid: false, message: '密码过于简单,请使用更复杂的密码' };
}
return { valid: true };
}
// 验证token
async function validateToken() {
resetToken = getParam('resetToken') || getParam('token');
@@ -373,6 +424,11 @@
return;
}
const cleanUrl = new URL(window.location.href);
cleanUrl.searchParams.delete('resetToken');
cleanUrl.searchParams.delete('token');
window.history.replaceState({}, document.title, cleanUrl.pathname + cleanUrl.search + cleanUrl.hash);
// Token存在显示表单
showSection('form');
}
@@ -386,8 +442,9 @@
const submitBtn = document.getElementById('submitBtn');
// 验证
if (password.length < 6) {
showFormAlert('error', '密码长度至少6位');
const passwordCheck = validateAccountPassword(password);
if (!passwordCheck.valid) {
showFormAlert('error', passwordCheck.message);
return;
}
@@ -401,9 +458,14 @@
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 处理中...';
try {
const csrfToken = await ensureCsrfToken();
const res = await fetch('/api/password/reset', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
headers: {
'Content-Type': 'application/json',
...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {})
},
body: JSON.stringify({
token: resetToken,
new_password: password