实验五-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(主程序)

python 复制代码
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(基础模板)

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(首页)

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(登录页)

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(注册页)

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

注册时存储哈希值

usersusername = generate_password_hash(password)

登录时验证

if check_password_hash(usersusername, 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:

usersusername = 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(usersusername, 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

相关推荐
JustHappy3 小时前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
老毛肚3 小时前
jeecg-boot-base-core 02 day
javascript·python
yaoxin5211233 小时前
434. Java 日期时间 API - Period 基于日期的时间段
java·开发语言·python
Hommy883 小时前
【剪映小助手】添加图片接口(Add Images)
后端·github·剪映小助手·视频剪辑自动化
GetcharZp4 小时前
别再盲目用 OpenCV 读图了,这才是 CV 预处理的终极杀手锏!
后端
岁月宁静4 小时前
RAG 文档摄入全链路,从原理到生产落地
vue.js·人工智能·python
JaydenAI4 小时前
[对比学习LangChain和MAF-07]如何引入人机交互的审批流程
python·ai·langchain·c#·agent·hitl·maf
神奇元创5 小时前
商用级光路加速卡:大模型推理的极速落地方案
python·神经网络·fpga开发·dsp开发
运筹vivo@5 小时前
Python ContextVar 底层机制与内存模型拆解
前端·数据库·python