4a1d949e41
完整 Web 管理平台,涵盖: P0 生产加固: - 会话超时(空闲+绝对) + CSRF 防护 + 登录失败限流 - HTTPS/TLS 证书管理(自签生成/上传/删除/过期提醒) - SSL Bump (HTTPS 透明代理) 可视化配置 - 配置文件 diff 预览 + 二次确认才写入 - 服务控制二次确认 + 操作期间按钮锁定 P1 运维能力: - 日志轮转管理(logrotate) + 日志状态监控 - 告警规则(5xx/命中率/磁盘/客户端流量) - 多 Squid 实例管理 + 一键切换 - squidclient mgr 实时性能指标 - 流量异常检测(突增/大文件/高频小包/新客户端) P2 日志分析增强: - 日志持久化到 SQLite + 历史时间范围查询 - 导出 CSV/JSON(日志/KPI/异常/审计) - GeoIP 地图(Leaflet + ip-api.com 离线可选 GeoLite2) - 每客户端 24h 趋势图 - 自定义 Squid logformat 解析器 P3 体验锦上添花: - 暗/亮主题切换(cookie 持久化) - WebSSH 终端(xterm.js + paramiko) - 完整审计日志 + 用户管理 技术栈: Flask 3.0 + SQLAlchemy 2.0 + SQLite + Chart.js + Leaflet 总代码量: ~16500 行 (15 Python 模块 + 34 模板 + CSS) 路由数: 73
98 lines
4.0 KiB
HTML
98 lines
4.0 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}修改密码 - Squid Manager{% endblock %}
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<h1>🔒 修改密码</h1>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<form method="post" class="form-narrow" id="change-pw-form">
|
|
<input type="hidden" name="_csrf" value="{{ csrf_token() }}">
|
|
<div class="form-group">
|
|
<label>旧密码</label>
|
|
<input type="password" name="old_password" required class="form-input"
|
|
autocomplete="current-password">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>新密码 <span class="hint">至少 8 位,含大小写+数字</span></label>
|
|
<input type="password" name="new_password" id="new_password" required
|
|
class="form-input" autocomplete="new-password" minlength="8">
|
|
<div class="pw-strength" id="pw-strength">
|
|
<div class="pw-strength-bar"><div class="pw-strength-fill" id="pw-fill"></div></div>
|
|
<span class="pw-strength-label" id="pw-label"></span>
|
|
<span class="pw-strength-hint" id="pw-hint"></span>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>确认新密码</label>
|
|
<input type="password" name="confirm_password" id="confirm_password" required
|
|
class="form-input" autocomplete="new-password">
|
|
<div class="pw-match" id="pw-match"></div>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary">💾 修改</button>
|
|
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary">取消</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
const newPw = document.getElementById('new_password');
|
|
const confirmPw = document.getElementById('confirm_password');
|
|
const fill = document.getElementById('pw-fill');
|
|
const label = document.getElementById('pw-label');
|
|
const hint = document.getElementById('pw-hint');
|
|
const matchEl = document.getElementById('pw-match');
|
|
|
|
const COLORS = ['#ef4444', '#f59e0b', '#eab308', '#10b981', '#059669'];
|
|
const LABELS = ['极弱', '弱', '中', '强', '很强'];
|
|
|
|
function score(pw) {
|
|
if (!pw) return 0;
|
|
let s = 0;
|
|
if (pw.length >= 8) s++;
|
|
if (pw.length >= 12) s++;
|
|
if (/[A-Z]/.test(pw) && /[a-z]/.test(pw)) s++;
|
|
if (/\d/.test(pw)) s++;
|
|
if (/[^A-Za-z0-9]/.test(pw)) s++;
|
|
if (pw.toLowerCase() === 'admin' || pw.toLowerCase() === 'password' ||
|
|
pw.toLowerCase() === '123456' || pw.toLowerCase() === 'squid' ||
|
|
pw.toLowerCase() === 'changeme') s = Math.max(0, s - 2);
|
|
return Math.min(4, Math.max(0, s));
|
|
}
|
|
|
|
newPw.addEventListener('input', () => {
|
|
const s = score(newPw.value);
|
|
fill.style.width = ((s + 1) * 20) + '%';
|
|
fill.style.background = COLORS[s];
|
|
label.textContent = '强度: ' + LABELS[s];
|
|
label.style.color = COLORS[s];
|
|
if (s < 2) hint.textContent = '建议 8+ 字符,含大小写+数字+特殊字符';
|
|
else if (s < 3) hint.textContent = '可加入特殊字符进一步提升';
|
|
else hint.textContent = '密码强度良好';
|
|
if (newPw.value && confirmPw.value) checkMatch();
|
|
});
|
|
confirmPw.addEventListener('input', checkMatch);
|
|
function checkMatch() {
|
|
if (!confirmPw.value) { matchEl.textContent = ''; return; }
|
|
if (newPw.value === confirmPw.value) {
|
|
matchEl.textContent = '✓ 两次输入一致';
|
|
matchEl.style.color = '#10b981';
|
|
} else {
|
|
matchEl.textContent = '✗ 两次输入不一致';
|
|
matchEl.style.color = '#ef4444';
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
.pw-strength { margin-top: 8px; font-size: 12px; }
|
|
.pw-strength-bar { height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; margin-bottom: 4px; }
|
|
.pw-strength-fill { height: 100%; width: 0; background: #ef4444; transition: width 0.2s, background 0.2s; }
|
|
.pw-strength-label { font-weight: 600; }
|
|
.pw-strength-hint { color: var(--text-muted); margin-left: 8px; }
|
|
.pw-match { font-size: 12px; margin-top: 4px; min-height: 16px; }
|
|
</style>
|
|
{% endblock %}
|