【python实用小脚本-118】基于Flask的用户认证系统:app.py、forms.py与user.py解析

发布于:2025-06-27 ⋅ 阅读:(19) ⋅ 点赞:(0)

在当今的网络应用中,用户认证是一个不可或缺的功能。无论是社交平台、电商平台还是企业管理系统,都需要确保只有授权用户才能访问特定的资源。本文将详细介绍一个基于 Flask 框架的用户认证系统,该系统由三个主要文件组成:app.pyforms.pyuser.py。通过解析这三个文件,我们将深入了解如何实现一个安全、高效的用户注册、登录和注销功能。

一、系统概述

这个用户认证系统使用 Flask 框架构建,Flask 是一个轻量级的 Python Web 框架,以其灵活性和易于扩展而受到开发者的喜爱。系统的主要功能包括用户注册、登录、注销以及访问控制。用户注册时需要填写个人信息,包括用户名、密码、邮箱等。登录时,系统会验证用户输入的用户名和密码是否正确。一旦用户登录成功,他们可以访问受保护的页面,如个人仪表盘。用户注销后,将无法再访问这些受保护的页面,直到重新登录。

二、代码功能详细分析

(一)app.py:Flask 应用的入口

app.py 是整个 Flask 应用的入口文件,它负责初始化 Flask 应用、定义路由和视图函数,并启动服务器。

from flask import Flask, render_template, flash, redirect, session
from functools import wraps
import setup.config as config
from user import User

app = Flask(__name__, template_folder="templates", static_folder='static')

在代码的开头,我们导入了必要的模块和类。Flask 是 Flask 框架的核心类,render_template 用于渲染 HTML 模板,flash 用于显示消息提示,redirect 用于重定向用户到其他页面,session 用于管理用户会话。wraps 是一个装饰器,用于保留原始函数的元信息。setup.config 是一个配置模块,包含了数据库配置和其他应用配置。User 类包含了用户注册、登录和注销的逻辑。

接下来,我们定义了一个名为 login_required 的装饰器,用于保护需要用户登录才能访问的路由。

def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if 'logged_in' in session:
            return f(*args, **kwargs)
        else:
            flash('Unauthorized. Please login.', 'danger')
            return redirect('/')
    return wrap

这个装饰器检查用户是否已经登录(即 session 中是否存在 logged_in)。如果用户已经登录,它将正常执行视图函数;否则,它会显示一个错误消息,并将用户重定向到登录页面。

然后,我们定义了三个路由://logout/dashboard

@app.route('/', methods=['POST', 'GET'])
def register():
    return User().register()

@app.route('/logout')
def logout():
    return User().logout()

@app.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html')

/ 路由是用户注册和登录的页面,它调用了 User 类的 register 方法。/logout 路由用于用户注销,它调用了 User 类的 logout 方法。/dashboard 路由是用户登录后的仪表盘页面,它使用了 login_required 装饰器来保护页面,只有登录用户才能访问。

最后,我们启动了 Flask 应用。

if __name__ == "__main__":
    app.secret_key = config.secret_key
    app.run()

我们从配置模块中获取了 secret_key,并将其设置为 Flask 应用的密钥。然后,我们调用了 app.run() 来启动服务器。

(二)forms.py:表单定义

forms.py 文件定义了用户注册和登录所需的表单。它使用了 WTForms 库,这是一个功能强大的表单处理库,支持各种类型的字段和验证器。

from wtforms import Form, StringField, PasswordField, validators, SubmitField

我们导入了 Form 类以及所需的字段类型和验证器。

首先,我们定义了 registerForm 类,用于用户注册。

class registerForm(Form):
    name = StringField(
        '',
        [validators.DataRequired(), validators.Length(min=1, max=50)],
        render_kw={"placeholder": "Name"})
    username = StringField(
        '',
        [validators.Length(min=4, max=25)],
        render_kw={"placeholder": "Username"})
    email = StringField(
        '',
        [validators.Length(min=6, max=150)],
        render_kw={"placeholder": "Email"})
    password = PasswordField('', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message="Passwords do not match!")
    ], render_kw={"placeholder": "Password"})
    confirm = PasswordField('', render_kw={"placeholder": "Confirm Password"})
    submit1 = SubmitField('Register')

registerForm 包含了用户注册所需的所有字段:nameusernameemailpasswordconfirm。每个字段都使用了相应的验证器,例如 DataRequired 确保字段不为空,Length 确保字段长度符合要求,EqualTo 确保密码和确认密码一致。render_kw 参数用于设置字段的 HTML 属性,例如占位符文本。

接下来,我们定义了 loginForm 类,用于用户登录。

class loginForm(Form):
    username = StringField('', render_kw={"placeholder": "Username"})
    password = PasswordField('', [
        validators.DataRequired()
    ], render_kw={"placeholder": "Password"})
    submit2 = SubmitField('Login')

loginForm 包含了用户登录所需的字段:usernamepasswordusername 字段没有使用验证器,因为用户名可以为空(在实际应用中,你可能希望添加验证器来确保用户名不为空)。password 字段使用了 DataRequired 验证器,确保用户输入了密码。submit2 是一个提交按钮字段。

(三)user.py:用户逻辑处理

user.py 文件包含了用户注册、登录和注销的逻辑。它使用了 FlaskWTForms,以及 passlib 库来处理密码加密和验证。

from flask import render_template, flash, redirect, session, request
from forms import registerForm, loginForm
from passlib.hash import sha256_crypt
import setup.config as config
import uuid

在代码的开头,我们导入了必要的模块和类。render_templateflashredirectsession 是 Flask 提供的函数和对象,用于处理模板渲染、消息提示、重定向和用户会话。registerFormloginForm 是我们在 forms.py 中定义的表单类。sha256_cryptpasslib 库提供的密码加密和验证工具。setup.config 是配置模块,包含了数据库配置和其他应用配置。uuid 是一个用于生成唯一标识符的模块。

接下来,我们定义了 User 类。

class User:
    def start_session(self, user):
        del user['password']
        session['logged_in'] = True
        session['user'] = user

User 类包含了一个名为 start_session 的方法,用于启动用户会话。它从用户字典中删除了密码字段,然后将 logged_in 设置为 True,并将用户信息存储在 session 中。

然后,我们定义了 register 方法,用于处理用户注册。

def register(self):
    reg_form = registerForm(request.form)
    login_form = loginForm(request.form)
    if request.method == "POST":
        if reg_form.submit1.data and reg_form.validate():
            user = {
                "_id": uuid.uuid4().hex,
                "name": reg_form.name.data,
                "email": reg_form.email.data,
                "username": reg_form.username.data,
                "password": reg_form.password.data}
            user['password'] = sha256_crypt.encrypt(user['password'])
            if config.db.users.find_one({"email": user['email']}):
                error = "Email already exists!"
                return render_template(
                    config.template,
                    error=error,
                    reg_form=reg_form,
                    login_form=login_form)
            if config.db.users.insert_one(user):
                self.start_session(user)
                flash('You are now registered and can log in!', 'success')
                return render_template(
                    config.template,
                    reg_form=reg_form,
                    login_form=login_form)
        elif login_form.submit2.data and login_form.validate():
            user = config.db.users.find_one(
                {"username": login_form.username.data})
            if user:
                if sha256_crypt.verify(
                        login_form.password.data, user['password']):
                    self.start_session(user)
                    return render_template('dashboard.html')
                else:
                    error = 'Incorrect login details!'
                    return render_template(
                        config.template,
                        error=error,
                        reg_form=reg_form,
                        login_form=login_form)
            else:
                error = 'Username not found!'
                return render_template(
                    config.template,
                    error=error,
                    reg_form=reg_form,
                    login_form=login_form)
        error = 'Check the registered details!'
        return render_template(
            config.template,
            error=error,
            reg_form=reg_form,
            login_form=login_form)
    else:
        try:
            return render_template(
                config.template,
                reg_form=reg_form,
                login_form=login_form)
        except Exception:
            return "Given template does not exists."

register 方法首先创建了 registerFormloginForm 的实例。如果请求方法是 POST,它会检查用户是否提交了注册表单或登录表单。如果用户提交了注册表单并且表单验证通过,它会创建一个用户字典,包含用户的基本信息和加密后的密码。然后,它会检查数据库中是否已经存在该用户的邮箱,如果存在,它会显示一个错误消息。如果不存在,它会将用户信息插入数据库,并启动用户会话。如果用户提交了登录表单并且表单验证通过,它会从数据库中查找用户,如果用户存在并且密码匹配,它会启动用户会话并将用户重定向到仪表盘页面。如果密码不匹配或用户不存在,它会显示一个错误消息。

最后,我们定义了 logout 方法,用于处理用户注销。

def logout(self):
    session.clear()
    flash("You are now logged out!", "success")
    return redirect('/')

logout 方法清除了用户会话,并显示一个成功消息,然后将用户重定向到登录页面。

三、总结

通过解析 app.pyforms.pyuser.py 这三个文件,我们深入了解了一个基于 Flask 框架的用户认证系统的实现细节。这个系统使用了 Flask 的会话管理、WTForms 的表单处理和 passlib 的密码加密功能,实现了用户注册、登录、注销和访问控制。在实际应用中,你可以根据自己的需求对这个系统进行扩展和优化,例如添加更多的用户信息字段、使用更复杂的密码加密算法、实现用户角色管理等。

源码获取

完整代码已开源,包含详细的注释文档:
🔗 [GitCode仓库] https://gitcode.com/laonong-1024/python-automation-scripts
📥 [备用下载] https://pan.quark.cn/s/654cf649e5a6 提取码:f5VG


网站公告

今日签到

点亮在社区的每一天
去签到