feat: 密码强度多级校验 — low/medium/high/very_high

- site_settings 新增 password.strength 配置项
- 四级:low(len>=8) / medium(两类) / high(三类+无连续) / very_high(四类+无连续)
- 连续字符检查:重复/升序/降序/键盘水平/键盘垂直序列
- 注册和改密接口统一读取配置
- 前端 register.js 动态校验 + 管理后台安全设置区
This commit is contained in:
2026-06-22 00:54:21 +08:00
parent e9b7401dc9
commit 9a496d3055
8 changed files with 225 additions and 11 deletions

View File

@ -23,6 +23,10 @@
var toast = document.getElementById('toast');
var emailInput = document.getElementById('email');
var passwordInput = document.getElementById('password');
// 密码强度提示从 data 属性读取
var pwHint = passwordInput.getAttribute('placeholder') || '密码至少 8 位';
var pwMinLen = 8;
var pwLevel = passwordInput.getAttribute('data-pw-level') || 'medium';
var confirmPasswordInput = document.getElementById('confirmPassword');
var rememberMeCheckbox = document.getElementById('rememberMe');
var guidelinesAgreedCheckbox = document.getElementById('guidelinesAgreed');
@ -178,7 +182,7 @@
var password = passwordInput.value;
var confirm = confirmPasswordInput.value;
var emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
var passwordValid = password.length >= 8 && /[a-z]/.test(password) && /[A-Z]/.test(password) && /\d/.test(password);
var passwordValid = checkPWStrength(password);
var confirmValid = passwordValid && confirm === password;
submitBtn.disabled = !(emailValid && passwordValid && confirmValid);
}
@ -195,9 +199,22 @@
checkFormValidity();
});
function checkPWStrength(pw) {
if (pw.length < pwMinLen) return false;
var cats = 0;
if (/[a-z]/.test(pw)) cats++;
if (/[A-Z]/.test(pw)) cats++;
if (/\d/.test(pw)) cats++;
if (/[^a-zA-Z0-9]/.test(pw)) cats++;
if (pwLevel === 'low') return true;
if (pwLevel === 'medium') return cats >= 2;
if (pwLevel === 'high' || pwLevel === 'very_high') return cats >= (pwLevel === 'very_high' ? 4 : 3);
return cats >= 2;
}
passwordInput.addEventListener('input', function () {
var v = passwordInput.value;
if (v && (v.length < 8 || !/[a-z]/.test(v) || !/[A-Z]/.test(v) || !/\d/.test(v))) {
if (v && !checkPWStrength(v)) {
passwordInput.classList.add('error');
passwordError.style.display = 'block';
} else {