在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)攻击。