在Flask中,g对象是一个特殊类型的对象,被称为"上下文全局变量"。它在一次请求的生命周期内存储信息,并且可以在整个请求过程中访问和共享。
g对象对于存储用户登录信息非常有用。例如,当用户通过验证登录时,您可以将用户的身份信息存储在g.user中,以便在当前请求的其他部分使用。这样,在请求的其他函数、方法或视图中,您可以轻松地访问和验证用户的登录状态,而无需在每个函数中重复验证。
通过在g对象中存储用户的登录信息,您可以确保在请求的整个处理过程中使用相同的用户信息,而无需重复查询数据库或将信息传递给每个函数。这提供了一种方便的方式来访问和共享请求范围的数据,使您能够轻松地处理用户身份验证和授权等功能。
下面是如何在 Flask 中使用 g 对象来保存、访问用户登录信息以及注销登录的示例代码:
首先,假设我们有一个 UserModel 表在 MySQL 数据库中,且已经建立了一个 SQLAlchemy 模型来与之交互。
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class UserModel(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, nullable=False) password = db.Column(db.String(128), nullable=False)
该代码为Flask应用程序中的用户模型设置了基本结构,包括用户的ID、用户名和密码。SQLAlchemy将处理Python类与相应数据库表之间的映射,允许您使用UserModel类执行数据库操作。
用户登录并保存登录状态
接着我们在 Flask 应用中使用 g
对象和 before_request
钩子函数来保存用户登录信息:
from flask import Flask, g, session, abort from flask_login import LoginManager, login_user from flask_migrate import Migrate # 初始化 Flask 应用 app = Flask(__name__) # 初始化 migrate = Migrate(app, db) db.init_app(app) @app.before_request def my_before_request(): user_id = session.get("user_id") if user_id: user = UserModel.query.get(user_id) setattr(g, "user", user) else: setattr(g, "user", None) @app.context_processor def my_context_processor(): return {"user": g.user}
第一个函数 my_before_request 使用 @app.before_request 装饰器进行修饰。这意味着它将在每次请求之前执行。该函数的目的是在会话中检查是否存在 “user_id” 键,并根据该键的值来设置全局对象 g 的 “user” 属性。具体来说,它从会话中获取 “user_id” 的值,然后使用该值查询数据库中的 UserModel 表,获取对应的用户对象,并将该对象设置为 g.user。如果 “user_id” 不存在或对应的用户对象未找到,则将 g.user 设置为 None。
第二个函数 my_context_processor 使用 @app.context_processor 装饰器进行修饰。这意味着它将注册为一个上下文处理器,用于在模板中设置全局变量。该函数返回一个字典,其中键为 “user”,值为 g.user。这样,在渲染模板时,就可以在模板中使用 user 变量来访问当前用户的信息。
总结起来,这段代码的作用是在每次请求之前检查会话中的用户ID,查询数据库获取用户对象,并将用户对象设置为全局变量,以便在模板中使用。这样,在渲染模板时,就可以方便地获取当前用户的信息。
然后写登录的实现路由
@app.route("/login", methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template("login.html") else: username = form.username.data password = form.password.data #表单登录验证 user = UserModel.query.filter_by(username=username).first() if not user: return redirect(url_for("auth.login")) if user.password==password: session['user_id'] = user.id #添加user_id到session中 return redirect("/") else: return render_template('pwd_error.html')
退出登录状态
在 Flask 中,你可以通过从 session 中删除用户 ID 来实现用户的注销。下面是一个简单的注销路由的示例:
from flask import redirect, url_for @app.route("/logout") def logout(): session.clear() return redirect("/")
这个注销路由首先从 session 中删除了 ‘user_id’。然后路由重定向到了首页。
注意,你还需要确保在用户登出后,不能再通过更改浏览器的 user_id cookie 来伪装为已注销的用户。这通常通过将 session 的 secure 属性设置为 True 来实现,这样 cookie 就只能在 HTTPS 连接中传输。同时,将 session 的 httponly 属性设置为 True 可以阻止 JavaScript 访问到 cookie,这样可以避免跨站脚本(XSS)攻击。