feat: 完善登录认证系统

- 首次使用强制设置密码(至少6位)
- 密码存数据库(SHA256哈希),前端可修改
- 登录失败5次锁定5分钟,防爆破
- 导航栏添加修改密码入口
- 移除硬编码默认密码
This commit is contained in:
2026-04-02 12:11:09 +08:00
parent 6ab6666cac
commit c293f3d4ac
8 changed files with 278 additions and 46 deletions

View File

@@ -35,7 +35,8 @@
<a class="nav-link" href="/tasks/"><i class="bi bi-list-task"></i> 任务</a>
<a class="nav-link" href="/accounts/"><i class="bi bi-people"></i> 账号</a>
<a class="nav-link" href="/orders/"><i class="bi bi-receipt"></i> 订单</a>
<a class="nav-link text-warning-emphasis" href="/logout"><i class="bi bi-box-arrow-right"></i></a>
<a class="nav-link text-warning-emphasis" href="/change_password" title="修改密码"><i class="bi bi-key"></i></a>
<a class="nav-link text-warning-emphasis" href="/logout" title="退出"><i class="bi bi-box-arrow-right"></i></a>
</div>
</div>
</nav>

View File

@@ -0,0 +1,33 @@
{% extends "base.html" %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-5">
<div class="card">
<div class="card-body p-4">
<h5 class="mb-3"><i class="bi bi-key"></i> 修改密码</h5>
{% if error %}
<div class="alert alert-danger py-2" style="border-radius:10px;font-size:.85rem">{{ error }}</div>
{% endif %}
{% if success %}
<div class="alert alert-success py-2" style="border-radius:10px;font-size:.85rem">{{ success }}</div>
{% endif %}
<form method="POST">
<div class="mb-3">
<label class="form-label">原密码</label>
<input type="password" class="form-control" name="old_password" required>
</div>
<div class="mb-3">
<label class="form-label">新密码至少6位</label>
<input type="password" class="form-control" name="new_password" required minlength="6">
</div>
<div class="mb-3">
<label class="form-label">确认新密码</label>
<input type="password" class="form-control" name="new_password2" required minlength="6">
</div>
<button type="submit" class="btn btn-primary w-100">确认修改</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -10,27 +10,24 @@
body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh;
display: flex; align-items: center; justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.login-card { width: 360px; border-radius: 18px; border: none;
box-shadow: 0 8px 40px rgba(0,0,0,.2); }
.login-header { text-align: center; padding: 2rem 2rem 1rem; }
.login-header i { font-size: 2.5rem; color: #667eea; }
.login-header h4 { margin-top: .8rem; font-weight: 600; color: #333; }
.login-body { padding: 0 2rem 2rem; }
.card { width: 360px; border-radius: 18px; border: none; box-shadow: 0 8px 40px rgba(0,0,0,.2); }
.card-header { text-align: center; padding: 2rem 2rem 1rem; background: none; border: none; }
.card-header i { font-size: 2.5rem; color: #667eea; }
.card-header h4 { margin-top: .8rem; font-weight: 600; color: #333; }
.card-body { padding: 0 2rem 2rem; }
.form-control { border-radius: 10px; padding: .6rem 1rem; }
.form-control:focus { border-color: #667eea; box-shadow: 0 0 0 .2rem rgba(102,126,234,.15); }
.btn-login { background: linear-gradient(135deg, #667eea, #764ba2); border: none;
border-radius: 10px; padding: .6rem; font-weight: 500; width: 100%; }
.btn-login:hover { opacity: .9; }
.btn-primary { background: linear-gradient(135deg, #667eea, #764ba2); border: none;
border-radius: 10px; padding: .6rem; font-weight: 500; width: 100%; }
.alert { border-radius: 10px; font-size: .85rem; }
</style>
</head>
<body>
<div class="card login-card">
<div class="login-header">
<div class="card">
<div class="card-header">
<i class="bi bi-lightning-charge-fill"></i>
<h4>微店抢购管理</h4>
</div>
<div class="login-body">
<div class="card-body">
{% if error %}
<div class="alert alert-danger py-2">{{ error }}</div>
{% endif %}
@@ -39,7 +36,7 @@
<input type="password" class="form-control" name="password"
placeholder="请输入访问密码" autofocus required>
</div>
<button type="submit" class="btn btn-primary btn-login">登 录</button>
<button type="submit" class="btn btn-primary">登 录</button>
</form>
</div>
</div>

50
templates/setup.html Normal file
View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初始设置 - 微店抢购管理</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<style>
body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh;
display: flex; align-items: center; justify-content: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.card { width: 380px; border-radius: 18px; border: none; box-shadow: 0 8px 40px rgba(0,0,0,.2); }
.card-header { text-align: center; padding: 2rem 2rem 1rem; background: none; border: none; }
.card-header i { font-size: 2.5rem; color: #667eea; }
.card-header h4 { margin-top: .8rem; font-weight: 600; color: #333; }
.card-header p { color: #888; font-size: .85rem; }
.card-body { padding: 0 2rem 2rem; }
.form-control { border-radius: 10px; padding: .6rem 1rem; }
.btn-primary { background: linear-gradient(135deg, #667eea, #764ba2); border: none;
border-radius: 10px; padding: .6rem; font-weight: 500; width: 100%; }
.alert { border-radius: 10px; font-size: .85rem; }
</style>
</head>
<body>
<div class="card">
<div class="card-header">
<i class="bi bi-shield-lock-fill"></i>
<h4>首次使用设置</h4>
<p>请设置管理密码至少6位</p>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger py-2">{{ error }}</div>
{% endif %}
<form method="POST">
<div class="mb-3">
<input type="password" class="form-control" name="password"
placeholder="设置密码" autofocus required minlength="6">
</div>
<div class="mb-3">
<input type="password" class="form-control" name="password2"
placeholder="确认密码" required minlength="6">
</div>
<button type="submit" class="btn btn-primary">确认设置</button>
</form>
</div>
</div>
</body>
</html>