一、实验目的和任务
1.掌握Flask框架的基本使用方法
2.理解Web应用的会话管理机制
3.实现用户认证系统的基本功能
4.学习模板继承和表单处理技术
要求:请将思考题的答案写在实验报告中
二、实验内容
1.基础环境搭建:创建项目目录结构、安装必要依赖包
2.核心功能实现:用户注册(用户名、密码)、用户登录验证、会话状态管理、用户退出功能
3.前端界面开发:基础模板设计、注册/登录表单实现
4.系统测试验证:注册新用户测试、登录功能测试、会话保持测试
三、实验步骤
1. 项目结构
/flask_auth_system
├── app.py
├── templates/
├── base.html
├── index.html
├── login.html
└── register.html
2. app.py(主程序)
from flask import Flask, render_template, request, redirect, url_for, session, flash
app = Flask(__name__)
app.secret_key = '1220911101_fyt_secret_key'
# 模拟用户数据库
users = {
'admin': 'admin123' # 预置测试用户
}
@app.route('/')
def home():
if 'username' in session:
return render_template('index.html', username=session['username'])
return redirect(url_for('login'))
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username in users:
flash('用户名已存在')
else:
users[username] = password
flash('注册成功,请登录')
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username in users and users[username] == password:
session['username'] = username
flash('登录成功')
return redirect(url_for('home'))
flash('用户名或密码错误')
return render_template('login.html')
@app.route('/logout')
def logout():
session.pop('username', None)
flash('您已成功退出')
return redirect(url_for('home'))
if __name__ == '__main__':
app.run(debug=True)
3. templates/base.html(基础模板)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}1220911101 符亚通 - Flask登录系统{% endblock %}</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
width: 80%;
margin: 0 auto;
padding: 20px;
background: #fff;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
margin-top: 50px;
}
.auth-form {
max-width: 400px;
margin: 0 auto;
}
.flash-messages {
color: red;
margin-bottom: 20px;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 8px;
margin: 8px 0;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="flash-messages">
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
</body>
</html>
4. templates/index.html(首页)
{% extends "base.html" %}
{% block title %}首页 - 1220911101 符亚通{% endblock %}
{% block content %}
<div class="welcome">
{% if 'username' in session %}
<h2>欢迎, {{ username }}!</h2>
<p>您已成功登录系统</p>
<a href="{{ url_for('logout') }}"><button>退出登录</button></a>
{% else %}
<h2>欢迎来到1220911101的Flask登录系统</h2>
<p>请先<a href="{{ url_for('login') }}">登录</a>或<a href="{{ url_for('register') }}">注册</a></p>
{% endif %}
</div>
{% endblock %}
5. templates/login.html(登录页)
{% extends "base.html" %}
{% block title %}用户登录 - 1220911101 符亚通{% endblock %}
{% block content %}
<div class="auth-form">
<h2>用户登录</h2>
<form method="POST" action="{{ url_for('login') }}">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">登录</button>
</form>
<p>还没有账号? <a href="{{ url_for('register') }}">立即注册</a></p>
</div>
{% endblock %}
6. templates/register.html(注册页)
{% extends "base.html" %}
{% block title %}用户注册 - 1220911101 符亚通{% endblock %}
{% block content %}
<div class="auth-form">
<h2>用户注册</h2>
<form method="POST" action="{{ url_for('register') }}">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">注册</button>
</form>
<p>已有账号? <a href="{{ url_for('login') }}">立即登录</a></p>
</div>
{% endblock %}
四.系统测试
1.测试注册流程:
输入空数据、注册已存在用户、成功注册新用户
2.测试登录流程:
错误凭证登录、正确凭证登录
3.测试会话保持:
刷新页面验证状态、测试退出功能

四、思考题
1.当前实现直接将密码明文存储在内存中,这存在什么安全隐患?应该如何改进?
安全隐患分析:
内存泄露风险:如果应用内存被转储,所有用户密码将直接暴露
数据库泄露风险:如果存储到数据库,管理员可以直接查看所有用户密码
违反隐私保护原则:不应存储用户原始密码
改进方案:
from werkzeug.security import generate_password_hash, check_password_hash
# 注册时存储哈希值
users[username] = generate_password_hash(password)
# 登录时验证
if check_password_hash(users[username], password):
# 验证通过
2.Flask的session是如何工作的?如果需要在多台服务器上部署应用,session存储需要做哪些调整?
默认使用客户端session,数据存储在cookie中
使用密钥签名防止篡改,但不加密内容
包含用户ID等基本信息
多服务器部署调整方案:
# 使用服务器端session存储
from flask_session import Session
app.config['SESSION_TYPE'] = 'redis' # 或其他服务器端存储
Session(app)
3.现有代码只验证了用户名是否存在,如果要添加以下验证规则应该如何实现:
密码长度不少于6位
用户名只能包含字母和数字
实现代码:
import re
def validate_username(username):
return bool(re.match('^[a-zA-Z0-9]+$', username))
@app.route('/register', methods=['POST'])
def register():
username = request.form['username']
password = request.form['password']
if len(password) < 6:
flash('密码长度不能少于6位')
elif not validate_username(username):
flash('用户名只能包含字母和数字')
elif username in users:
flash('用户名已存在')
else:
users[username] = generate_password_hash(password)
flash('注册成功')
4.如果要添加"记住我"功能,使登录状态可以保持更长时间,应该如何修改代码?
from datetime import timedelta
@app.route('/login', methods=['POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
remember = request.form.get('remember')
if check_password_hash(users[username], password):
session['username'] = username
if remember:
# 设置30天过期
app.permanent_session_lifetime = timedelta(days=30)
session.permanent = True
5.现有错误提示比较简略,如何给用户更友好的错误提示(如密码错误时提示剩余尝试次数)?
# 在应用全局添加尝试次数记录
login_attempts = {}
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
ip = request.remote_addr
# 初始化尝试次数
if ip not in login_attempts:
五、实验完整代码以及资源:
实验链接https://download.csdn.net/download/m0_73951999/91045318?spm=1001.2014.3001.5503