实验五-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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…