一、實驗目的和任務
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, flashapp = 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] = passwordflash('注冊成功,請登錄')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'] = usernameflash('登錄成功')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