實驗五-Flask的簡易登錄系統

一、實驗目的和任務

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87616.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87616.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87616.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WebSocket類明明注入了Bean,為什么報錯為null

在 WebSocket 類中注入 Bean 看似可行而注入 Bean 報錯為null&#xff0c;通常是由于Spring 的單例管理機制與 WebSocket 多實例創建特性沖突導致的&#xff0c;具體分析如下&#xff1a;原因分析Spring 的單例特性&#xff1a;Spring 默認以單例模式管理 Bean&#xff0c;即一…

Python 爬蟲開發指南:從基礎到實戰

在大數據時代&#xff0c;數據成為了寶貴的資源。Python 爬蟲作為高效獲取網絡數據的工具&#xff0c;受到越來越多開發者的關注。本文將詳細介紹 Python 爬蟲的相關知識&#xff0c;助你快速入門并掌握爬蟲開發的核心要點。 一、Python 爬蟲概述 Python 爬蟲&#xff0c;即網…

99、git 超時問題

報錯&#xff1a; Push failed ssh: connect to host github.com port 22: Connection timed out Could not read from remote repository

CountDownLatch 詳細介紹

CountDownLatch 是 Java 中 java.util.concurrent 包提供的一個同步工具類&#xff0c;用于協調多個線程之間的執行順序。它允許一個或多個線程等待&#xff0c;直到其他線程完成一組操作后繼續執行。CountDownLatch 是一種倒計數鎖存器&#xff0c;通過設置一個初始計數器值&a…

Hadoop之HDFS

Hadoop之HDFS HDFS的Shell操作 啟動Hadoop集群(方便后續測試) [atguigu@hadoop102 ~]$ sbin/start-dfs.sh [atguigu@hadoop102 ~]$ sbin/start-yarn.sh-help:輸出這個命令參數 [atguigu@hadoop102 ~]$ hadoop fs -help rm-ls:顯示目錄信息 [atguigu@hadoop102 ~]$ hadoop …

【1.4 漫畫PostgreSQL高級數據庫及國產數據庫對比】

&#x1f418; 漫畫PostgreSQL高級數據庫及國產數據庫對比 &#x1f468;?&#x1f4bb; 小明&#xff1a;“老王&#xff0c;除了MySQL&#xff0c;還有哪些優秀的關系型數據庫&#xff1f;國產數據庫發展得怎么樣&#xff1f;” &#x1f9d9;?♂? 架構師老王&#xff1a;…

OLT、ONU、ONT、SFU、HGU、ODN,它們是什么?它們之間有什么區別?

我們經常會看到OLT、ONU、ONT、SFU、HGU等設備術語。它們分別是什么?又有什么區別呢? PON組件:OLT、ONU、ONT和ODN 無源光網絡(PON)采用光纖和分路器&#xff0c;以點對多點拓撲將數據從單一源分發到多個用戶。與有源光網絡 (AON)不同&#xff0c;PON 僅在光域中運行&#…

sql USING 簡化 JOIN 操作

在 SQL 中&#xff0c;USING 是一種用于簡化 JOIN 操作的語法糖&#xff0c;它允許你明確指定連接表時所依據的列名。與傳統的 ON 子句相比&#xff0c;USING 提供了更簡潔的語法1. 基本語法與作用table1 JOIN table2 USING (column_name);將 table1 和 table2 中 column_name …

android開發中的 AndroidX 版本的查看 及 constraintLayout的簡單用法

1、查看庫的版本 平常我們經常會用到一些庫&#xff0c;但是不知道是什么版本&#xff0c;也不知道最新的是什么版本&#xff0c;當然最好的就是到官網去查看&#xff0c;或者三方的maven庫。 2、官方地址 AndroidX 版本 | Jetpack | Android Developers 3、比如我們來…

oracle鎖表,oracle解鎖表,oracle用戶連接數

一、查看被鎖的表 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode from v$locked_object lo, dba_objects ao, v$session sess where ao.object_id lo.object_id and lo.session_id sess.sid; 二、解鎖表語句 alter …

3D可視化:開啟多維洞察新時代

3D可視化技術以一種前所未有的方式&#xff0c;將數據、模型與現實世界緊密相連&#xff0c;為人們帶來了沉浸式、交互式的全新體驗&#xff0c;徹底革新了信息的呈現與理解方式。一、3D可視化的技術原理從技術本質來看&#xff0c;3D可視化基于一系列復雜而精妙的原理。通過數…

List中的對象進行排序處理

以下是使用 Java Stream 對對象列表按 id 和 age 排序的完整示例&#xff0c;包含升序和降序兩種場景&#xff1a; 1. 定義測試對象類 Getter Setter public class Person {private int id;private int age; }2. 排序實現代碼 import java.util.*; import java.util.stream.…

秋招Day14 - Redis - 底層結構

Redis都有哪些底層數據結構&#xff1f; 有八種核心的底層數據結構。 SDS Redis自己實現的動態字符串&#xff0c;SDS結構中直接存儲了已使用的字符數組長度len和未使用的字符數組長度free&#xff0c;所以獲取長度的時間復雜度是O(1)&#xff0c;還支持動態擴容&#xff0c…

使用Mac自帶的圖像捕捉導出 iPhone 相冊

用 數據線 將 iPhone 連接到 Mac必須是數據線,有些充電線插上去后無法識別到iphone在 iPhone 上點擊“信任此電腦”在 Mac 上打開應用&#xff1a;快速方式&#xff1a;按 Command Space 打開 Spotlight&#xff0c;輸入 圖像捕捉 或 Image Capture&#xff0c;回車或者從 /系…

【UniApp picker-view 多列對齊問題深度剖析與完美解決】

UniApp picker-view 多列對齊問題深度剖析與完美解決一次看似簡單的樣式調整&#xff0c;卻引發了對構建工具、CSS 預處理和組件渲染機制的深度思考創作時間: 2025/7/1 技術棧: UniApp Vue3 TypeScript PostCSS 問題級別: &#x1f534; 高級&#x1f3af; 問題背景 在開發 …

R Studio開發中記錄

1.如何將tar.gz格式的源碼R包編譯為zip格式的二進制R包。 R CMD INSTALL --build knhanes.tar.gz R CMD INSTALL --build nhanes.tar.gz 2.下載RTools RTools: Toolchains for building R and R packages from source on Windows 3.修改環境變量 PATH$PATH:/d/rtools45/usr…

量化交易中的隱藏模式識別:基于潛在高斯混合模型的機會挖掘

*——從市場噪聲中提取黃金信號的數學藝術** > 2025年3月,某對沖基金使用潛在高斯混合模型捕捉到銅期貨的異常波動模式,提前布局實現單月收益47%。核心代碼僅20行,卻顛覆了傳統技術分析范式。 --- ### 01 市場迷思:為何90%的交易者失敗? 金融市場本質是**非…

Qt窗口被外部(非Qt內部機制)強制銷毀,第二次再重復使用不顯示

在Qt開發中&#xff0c;窗口被外部&#xff08;非Qt內部機制&#xff09;強制銷毀 警告信息 External WM_DESTROY received for QWidgetWindow(0x108b8cbdb10, name"xxxxx") , parent: QWindow(0x0) , transient parent: QWindow(0x0) 使用場景 代碼結構如下&#x…

一文詳解Character AI:實用指南+ ChatGPT、Gemini對比分析

本指南將深入剖析Character AI的運行機制、功能特性及其存在的局限性。 近年來&#xff0c;生成式人工智能領域發展態勢迅猛&#xff0c;其應用范疇已遠超單純的文本生成領域。在眾多備受矚目的新興平臺中&#xff0c;Character AI是一款支持用戶以對話形式與人工智能生成角色…

遺傳算法的原理與實現示例

遺傳算法是一種受生物進化理論啟發的隨機優化算法&#xff0c;其核心思想是模擬自然界中 “物競天擇、適者生存” 的進化過程&#xff0c;通過對候選解的迭代優化&#xff0c;找到問題的最優解。 一、核心思想 遺傳算法將優化問題的候選解視為生物群體中的“個體”&#xff0c…