flask-login使用方法
烧瓶登录
Flask-Login 为 Flask 提供用户会话管理。它处理登录、注销和长时间记住用户会话的常见任务。
它会:
-
将活动用户的 ID 存储在Flask Session中,让您轻松登录和注销。
-
让您将视图限制为已登录(或已注销)的用户。(
login_required
) -
处理通常棘手的“记住我”功能。
-
帮助保护您的用户会话不被 cookie 窃贼窃取。
但是,它不会:
-
将特定的数据库或其他存储方法强加给您。您完全负责如何加载用户。
-
限制您使用用户名和密码、OpenID 或任何其他身份验证方法。
-
处理“是否登录”以外的权限。
-
处理用户注册或帐户恢复。
Installation
使用 pip 安装扩展:
$ pip install flask-login
配置你的应用程序
使用 Flask-Login 的应用程序中最重要的部分是 LoginManager
类。您应该在代码中的某处为您的应用程序创建一个,如下所示:
from flask_login import LoginManager
login_manager = LoginManager()
登录管理器包含让您的应用程序和 Flask-Login 一起工作的代码,例如如何从 ID 加载用户,当用户需要登录时将用户发送到哪里等等。
创建实际应用程序对象后,您可以将其配置为登录:
login_manager.init_app(app)
默认情况下,Flask-Login 使用会话进行身份验证。这意味着你必须在你的应用程序上设置密钥,否则 Flask 会给你一个错误信息告诉你这样做。请参阅有关会话的 Flask 文档 以了解如何设置密钥。
警告:确保使用“如何生成好的密钥”部分中的给定命令来生成您自己的密钥。不要使用示例一。
有关可用配置键的完整理解,请参阅源代码。
它是如何工作
您将需要提供user_loader
回调。此回调用于从会话中存储的用户 ID 重新加载用户对象。它应该获取用户的str
ID,并返回相应的用户对象。例如:
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
如果 ID 无效,它应该返回None
(不引发异常)。(在这种情况下,该 ID 将从会话中手动删除并继续处理。)
你的用户类
您用来表示用户的类需要实现这些属性和方法:
is_authenticated
-
True
如果用户通过身份验证,即他们提供了有效凭据,则该属性应返回。(只有经过身份验证的用户才能满足 的条件login_required
。) is_active
-
如果这是一个活动用户,则该属性应该返回
True
- 除了经过身份验证外,他们还激活了他们的帐户,没有被暂停,或者您的应用程序具有拒绝帐户的任何条件。非活动帐户可能无法登录(当然不会被强制)。 is_anonymous
get_id()
-
此方法必须返回
str
唯一标识此用户的 a,并可用于从user_loader
回调中加载用户。请注意,这必须是str
- 如果 ID 本身是 anint
或其他类型,则需要将其转换为str
.
为了更容易实现用户类,您可以继承 from UserMixin
,它为所有这些属性和方法提供默认实现。(不过,这不是必需的。)
登录示例
用户通过身份验证后,您可以使用该login_user
功能登录他们。
例如:
@app.route('/login', methods=['GET', 'POST'])
def login():
# Here we use a class of some kind to represent and validate our
# client-side form data. For example, WTForms is a library that will
# handle this for us, and we use a custom LoginForm to validate.
form = LoginForm()
if form.validate_on_submit():
# Login and validate the user.
# user should be an instance of your `User` class
login_user(user)
flask.flash('Logged in successfully.')
next = flask.request.args.get('next')
# is_safe_url should check if the url is safe for redirects.
# See http://flask.pocoo.org/snippets/62/ for an example.
if not is_safe_url(next):
return flask.abort(400)
return flask.redirect(next or flask.url_for('index'))
return flask.render_template('login.html', form=form)
警告:您必须验证next
参数的值。如果不这样做,您的应用程序将容易受到开放重定向的攻击。有关is_safe_url
查看此 Flask Snippet的示例实现。
就是这么简单。然后,您可以使用代理访问已登录的用户,该 current_user
代理在每个模板中都可用:
{% if current_user.is_authenticated %}
Hi {{ current_user.name }}!
{% endif %}
需要用户登录的视图可以使用装饰器进行login_required
装饰:
@app.route("/settings")
@login_required
def settings():
pass
当用户准备退出时:
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
他们将被注销,并且他们会话的所有 cookie 都将被清除。
自定义登录过程
默认情况下,当用户尝试login_required
在未登录的情况下访问视图时,Flask-Login 将闪烁一条消息并将他们重定向到登录视图。(如果未设置登录视图,它将以 401 错误中止。)
登录视图的名称可以设置为LoginManager.login_view
。例如:
login_manager.login_view = "users.login"
闪烁的默认消息是要自定义消息,请设置:Please log in to access this page.
LoginManager.login_message
login_manager.login_message = u"Bonvolu ensaluti por uzi tiun paĝon."
要自定义消息类别,请设置LoginManager.login_message_category
:
login_manager.login_message_category = "info"
当登录视图被重定向到时,它将next
在查询字符串中有一个变量,即用户试图访问的页面。或者,如果USE_SESSION_FOR_NEXT
is True
,则页面存储在 key 下的 session 中next
。
如果您想进一步自定义流程,请使用以下方式装饰函数 LoginManager.unauthorized_handler
:
@login_manager.unauthorized_handler
def unauthorized():
# do stuff
return a_response
例如:您正在将 Flask Login 与 Flask Restful 一起使用。在您的 API(名为 api 的蓝图)中,您不想重定向到登录页面,而是返回 Unauthorized 状态代码。:
from flask import redirect, url_for, request
from http import HTTPStatus
@login_manager.unauthorized_handler
def unauthorized():
if request.blueprint == 'api':
abort(HTTPStatus.UNAUTHORIZED)
return redirect(url_for('site.login'))
使用请求加载器自定义登录
有时您希望在不使用 cookie 的情况下登录用户,例如使用标头值或作为查询参数传递的 api 键。在这些情况下,您应该使用request_loader
回调。这个回调的行为应该和你的user_loader
回调一样,除了它接受 Flask 请求而不是 user_id。
例如,要支持从 url 参数和使用Authorization
标头的 Basic Auth 登录:
@login_manager.request_loader
def load_user_from_request(request):
# first, try to login using the api_key url arg
api_key = request.args.get('api_key')
if api_key:
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# next, try to login using Basic Auth
api_key = request.headers.get('Authorization')
if api_key:
api_key = api_key.replace('Basic ', '', 1)
try:
api_key = base64.b64decode(api_key)
except TypeError:
pass
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# finally, return None if both methods did not login the user
return None
匿名用户
默认情况下,当用户未实际登录时,current_user
设置为一个AnonymousUserMixin
对象。它具有以下属性和方法:
如果您对匿名用户有自定义要求(例如,他们需要有一个权限字段),您可以提供一个可调用的(类或工厂函数)来创建匿名用户LoginManager
:
login_manager.anonymous_user = MyAnonymousUser
记住我
默认情况下,当用户关闭浏览器时,Flask 会话被删除并且用户被注销。“记住我”可防止用户在关闭浏览器时意外退出。这并不意味着在用户退出后记住或在登录表单中预先填写用户的用户名或密码。
“记住我”功能可能很难实现。然而,Flask-Login 使它几乎透明 - 只需传递remember=True
给login_user
调用。cookie 将保存在用户的计算机上,如果不在会话中,Flask-Login 将自动从该 cookie 中恢复用户 ID。cookie 过期前的时间量可以通过 REMEMBER_COOKIE_DURATION
配置设置,也可以传递给login_user
. cookie 是防篡改的,因此如果用户篡改它(即插入其他人的用户 ID 代替他们自己的),cookie 将被拒绝,就好像它不存在一样。
该级别的功能是自动处理的。但是,您可以(并且应该,如果您的应用程序处理任何类型的敏感数据)提供额外的基础设施来提高记忆 cookie 的安全性。
替代代币
使用用户 ID 作为记忆令牌的值意味着您必须更改用户 ID 以使其登录会话无效。改进此问题的一种方法是使用替代用户 ID 而不是用户 ID。例如:
@login_manager.user_loader
def load_user(user_id):
return User.query.filter_by(alternative_id=user_id).first()
然后get_id
您的 User 类的方法将返回替代 id 而不是用户的主 ID:
def get_id(self):
return str(self.alternative_id)
这样,当用户更改密码时,您可以自由地将用户的替代 ID 更改为新的随机生成的值,这将确保他们的旧身份验证会话将不再有效。请注意,替代 ID 仍必须唯一标识用户……将其视为第二个用户 ID。
新登录
当用户登录时,他们的会话被标记为“新鲜”,这表明他们实际上在该会话上进行了身份验证。当他们的会话被破坏并使用“记住我”cookie重新登录时,它被标记为“非新鲜”。login_required
不区分新鲜度,这对大多数页面来说都很好。但是,更改个人信息等敏感操作需要重新登录。(无论如何,更改密码等操作都应始终要求重新输入密码。)
fresh_login_required
,除了验证用户是否登录之外,还将确保他们的登录是新鲜的。如果没有,它会将他们发送到他们可以重新输入凭据的页面。您可以login_required
通过设置 LoginManager.refresh_view
、needs_refresh_message
和 以与自定义 相同的方式自定义其行为needs_refresh_message_category
:
login_manager.refresh_view = "accounts.reauthenticate"
login_manager.needs_refresh_message = (
u"To protect your account, please reauthenticate to access this page."
)
login_manager.needs_refresh_message_category = "info"
或者通过提供您自己的回调来处理刷新:
@login_manager.needs_refresh_handler
def refresh():
# do stuff
return a_response
要再次将会话标记为新鲜,请调用该confirm_login
函数。
Cookie 设置
可以在应用程序设置中自定义 cookie 的详细信息。
|
存储“记住我”信息的 cookie 的名称。默认值: |
|
cookie 过期之前的时间量,作为 |
|
如果“记住我”cookie 应该跨域,请在此处设置域值(即 |
|
将“记住我”cookie 限制为特定路径。 默认: |
|
将“记住我”cookie 的范围限制为安全通道(通常是 HTTPS)。 默认: |
|
防止客户端脚本访问“记住我”cookie。 默认: |
|
如果设置为 |
|
将“记住我”cookie 限制为第一方或同一站点上下文。 默认: |
会话保护
虽然上述功能有助于保护您的“记住我”令牌免受 cookie 窃贼的侵害,但会话 cookie 仍然容易受到攻击。Flask-Login 包括会话保护,以帮助防止用户的会话被盗。
LoginManager
您可以在, 和应用程序的配置中配置会话保护。如果启用,它可以在任一basic
或strong
模式下运行。要将其设置在 上LoginManager
,请将 session_protection
属性设置为"basic"
or "strong"
:
login_manager.session_protection = "strong"
或者,禁用它:
login_manager.session_protection = None
默认情况下,它在"basic"
模式下被激活。SESSION_PROTECTION
通过将设置设置为None
、 "basic"
或,可以在应用程序的配置中禁用它"strong"
。
当会话保护处于活动状态时,每个请求都会为用户的计算机生成一个标识符(基本上是 IP 地址和用户代理的安全哈希)。如果会话没有关联的标识符,则生成的标识符将被存储。如果它有一个标识符,并且它与生成的标识符相匹配,那么该请求是 OK 的。
如果标识符在模式中不匹配basic
,或者会话是永久的,那么会话将被简单地标记为非新鲜的,并且任何需要重新登录的东西都会强制用户重新进行身份验证。(当然,您必须已经在适当的地方使用新登录才能产生效果。)
如果标识符在非永久会话的模式中不匹配,strong
则删除整个会话(以及如果存在的记忆令牌)。
禁用 API 的会话 Cookie
对 API 进行身份验证时,您可能希望禁用设置 Flask 会话 cookie。为此,请使用自定义会话界面,该界面会根据您在请求上设置的标志跳过保存会话。例如:
from flask import g
from flask.sessions import SecureCookieSessionInterface
from flask_login import user_loaded_from_request
@user_loaded_from_request.connect
def user_loaded_from_request(app, user=None):
g.login_via_request = True
class CustomSessionInterface(SecureCookieSessionInterface):
"""Prevent creating session from API requests."""
def save_session(self, *args, **kwargs):
if g.get('login_via_request'):
return
return super(CustomSessionInterface, self).save_session(*args,
**kwargs)
app.session_interface = CustomSessionInterface()
@user_loaded_from_request.connect
def user_loaded_from_request(self, user=None):
g.login_via_request = True
这可以防止在用户使用您的request_loader
.
自动化测试
为了让您更轻松地编写自动化测试,Flask-Login 提供了一个简单的自定义测试客户端类,它将为您设置用户的登录 cookie FlaskLoginClient
:. 要使用此自定义测试客户端类,请将其分配给 test_client_class
应用程序对象的属性,如下所示:
from flask_login import FlaskLoginClient
app.test_client_class = FlaskLoginClient
接下来,app.test_client()
像往常一样使用该方法制作一个测试客户端。但是,现在您可以将用户对象传递给此方法,您的客户端将自动使用此用户登录!
def test_request_with_logged_in_user():
user = User.query.get(1)
with app.test_client(user=user) as client:
# This request has user 1 already logged in!
client.get("/")
您也可以通过fresh_login
( bool
, 默认为True
) 将当前登录标记为新鲜或非新鲜。
请注意,您必须使用关键字参数,而不是位置参数。例如 test_client(user=user)
,将工作,但test_client(user)
不会。
由于此自定义测试客户端类的实现方式,您可能必须禁用会话保护才能使您的测试正常工作。如果启用了会话保护,登录会话将在模式下被标记为非新鲜或在使用测试客户端执行请求时basic
被完全拒绝。strong
Localization
默认情况下,LoginManager
用于flash
在用户需要登录时显示消息。这些消息是英文的。如果您需要本地化,请将 的localize_callback
属性设置为LoginManager
要在这些消息发送到之前使用这些消息调用的函数flash
,例如gettext
. 该函数将与消息一起调用,其返回值将被发送到flash
。
API 文档
本文档是从 Flask-Login 的源代码自动生成的。
配置登录
- 类 flask_login。LoginManager ( app = None , add_context_processor = True )[资源]
-
此对象用于保存用于登录的设置。实例
LoginManager
不绑定到特定应用程序,因此您可以在代码主体中创建一个,然后在工厂函数中将其绑定到您的应用程序。- init_app (应用程序, add_context_processor = True )[资源]
-
配置应用程序。这会注册一个
after_request
调用,并将LoginManager
其作为app.login_manager
.- 参数
-
-
app (
flask.Flask
) --flask.Flask
要配置的对象。 -
add_context_processor ( bool ) – 是否将上下文处理器添加到应用程序,以将
current_user
变量添加到模板。默认为True
.
-
-
当用户需要登录时调用它。如果您使用 注册回调
LoginManager.unauthorized_handler()
,那么它将被调用。否则,它将采取以下措施:-
如果应用程序正在使用蓝图,则使用 .找到当前蓝图的登录视图
blueprint_login_views
。如果应用程序未使用蓝图或未指定当前蓝图的登录视图,请使用login_view
. -
将用户重定向到登录视图。(他们尝试访问的页面将在
next
查询字符串变量中传递,因此如果存在而不是主页,您可以重定向到那里。或者,它将被添加到会话中,next
就像设置了 USE_SESSION_FOR_NEXT 一样。)
如果
LoginManager.login_view
未定义,那么它将简单地引发 HTTP 401(未经授权)错误。这应该从视图或 before/after_request 函数返回,否则重定向将无效。
- 需要_刷新( )[资源]
-
这在用户登录时调用,但他们需要重新验证,因为他们的会话已过时。如果您使用 注册回调
needs_refresh_handler
,那么它将被调用。否则,它将采取以下措施:-
将用户重定向到
LoginManager.refresh_view
. (他们试图访问的页面将在next
查询字符串变量中传递,因此如果存在,您可以重定向到那里而不是主页。)
如果
LoginManager.refresh_view
未定义,那么它将简单地引发 HTTP 401(未经授权)错误。这应该从视图或 before/after_request 函数返回,否则重定向将无效。
常规配置
- user_loader (回调)[资源]
-
这设置了从会话重新加载用户的回调。您设置的函数应采用用户 ID (a
str
) 并返回用户对象,或者None
如果用户不存在。- 参数
-
callback ( callable ) -- 用于检索用户对象的回调。
- request_loader (回调)[资源]
-
这设置了从 Flask 请求加载用户的回调。您设置的函数应该接受 Flask 请求对象并返回一个用户对象,或者
None
如果用户不存在。- 参数
-
callback ( callable ) -- 用于检索用户对象的回调。
- 匿名
-
产生匿名用户的类或工厂函数,在无人登录时使用。
- 登录视图
-
用户需要登录时重定向到的视图的名称。(如果您的身份验证机制在您的应用程序之外,这也可以是绝对 URL。)
- blueprint_login_views
-
这类似于 login_view,除了在处理蓝图时使用。它是一个字典,可以存储多个视图以重定向到不同的蓝图。重定向以键的形式列出,作为蓝图的名称,值作为重定向到路由。
- 登录信息
-
当用户被重定向到登录页面时闪烁的消息。
-
这将为该
unauthorized
方法设置回调,其中包括login_required
. 它不接受任何参数,并且应该返回要发送给用户的响应,而不是他们的正常视图。- 参数
-
callback ( callable ) -- 未授权用户的回调。
- 刷新视图
-
用户需要重新验证时重定向到的视图的名称。
- 需求刷新消息
-
当用户被重定向到重新认证页面时闪烁的消息。
- needs_refresh_handler (回调)[资源]
-
这将为该
needs_refresh
方法设置回调,其中包括fresh_login_required
. 它不接受任何参数,并且应该返回要发送给用户的响应,而不是他们的正常视图。- 参数
-
callback ( callable ) -- 未授权用户的回调。
登录机制
- 烧瓶登录。用户¶
-
当前用户的代理。
- 烧瓶登录。登录刷新( )[资源]
-
True
如果当前登录是新的,则返回。
- 烧瓶登录。login_remembered ( )[资源]
-
True
如果跨会话记住当前登录,则返回。
- 烧瓶登录。login_user(用户,记住=假,持续时间=无,强制=假,新鲜=真)[资源]
-
登录用户。您应该将实际的用户对象传递给它。如果用户的
is_active
属性是,除非是False
,否则他们将不会登录。force
True
True
如果登录尝试成功或False
失败(即因为用户不活动) ,这将返回。- 参数
-
-
user ( object ) -- 要登录的用户对象。
-
remember ( bool ) -- 会话过期后是否记住用户。默认为
False
. -
持续时间(
datetime.timedelta
) – 记忆 cookie 过期之前的时间量。如果None
使用设置中设置的值。默认为None
. -
force ( bool ) – 如果用户处于非活动状态,将其设置为
True
无论如何都会让他们登录。默认为False
. -
新鲜( bool ) - 将此设置为
False
将使用标记为非“新鲜”的会话登录用户。默认为True
.
-
- 烧瓶登录。注销用户( )[资源]
-
注销用户。(您不需要传递实际用户。)如果存在,这也将清除记住我的 cookie。
- 烧瓶登录。确认登录( )[资源]
-
这会将当前会话设置为新鲜的。从 cookie 重新加载会话时,它们会变得陈旧。
保护视图
- 烧瓶登录。login_required (函数)[资源]
-
如果你用这个装饰一个视图,它将确保当前用户在调用实际视图之前已经登录并进行了身份验证。(如果不是,它会调用
LoginManager.unauthorized
回调。)例如:@app.route('/post') @login_required def post(): pass
如果您只需要在某些时候要求您的用户登录,您可以这样做:
if not current_user.is_authenticated: return current_app.login_manager.unauthorized()
…本质上就是这个函数添加到你的视图中的代码。
单元测试时可以方便的全局关闭鉴权。要启用此功能,如果应用程序配置变量
LOGIN_DISABLED
设置为True
,则此装饰器将被忽略。笔记
根据CORS 预检请求的 W3 指南,HTTP
OPTIONS
请求免于登录检查。- 参数
-
func ( function ) -- 要装饰的视图函数。
- 烧瓶登录。fresh_login_required (函数)[资源]
-
如果你用它来装饰视图,它将确保当前用户的登录是新鲜的——即他们的会话不是从“记住我”cookie 中恢复的。敏感操作,如更改密码或电子邮件,应该受到保护,以阻止 cookie 窃贼的努力。
如果用户未通过身份验证,
LoginManager.unauthorized()
则正常调用。如果他们经过身份验证,但他们的会话不是新鲜的,它将调用LoginManager.needs_refresh()
。(在这种情况下,您需要提供LoginManager.refresh_view
.)就配置变量而言,其行为与
login_required()
装饰器相同。笔记
根据CORS 预检请求的 W3 指南,HTTP
OPTIONS
请求免于登录检查。- 参数
-
func ( function ) -- 要装饰的视图函数。
用户对象助手
- 类 flask_login。用户混合[资源]
-
这为 Flask-Login 期望用户对象拥有的方法提供了默认实现。
- 类 flask_login。匿名用户混合[资源]
-
这是代表匿名用户的默认对象。
Utilities
- 烧瓶登录。login_url ( login_view , next_url = None , next_field = 'next' )[资源]
-
Creates a URL for redirecting to a login page. If only
login_view
is provided, this will just return the URL for it. Ifnext_url
is provided, however, this will append anext=URL
parameter to the query string so that the login view can redirect back to that URL. Flask-Login’s default unauthorized handler uses this function when redirecting to your login url. To force the host name used, setFORCE_HOST_FOR_REDIRECTS
to a host. This prevents from redirecting to external sites if request headers Host or X-Forwarded-For are present.
- class flask_login.FlaskLoginClient(*args, **kwargs)[source]
-
A Flask test client that knows how to log in users using the Flask-Login extension.
Signals
See the Flask documentation on signals for information on how to use these signals in your code.
- flask_login.user_logged_in
-
Sent when a user is logged in. In addition to the app (which is the sender), it is passed
user
, which is the user being logged in.
- flask_login.user_logged_out
-
当用户注销时发送。除了应用程序(即发送者)之外,它还被传递
user
,即被注销的用户。
- 烧瓶登录。user_login_confirmed
-
在确认用户登录时发送,将其标记为新鲜。(正常登录时不会调用它。)除了应用程序之外,它不接收其他参数。
-
unauthorized
当在 .上调用该方法时发送LoginManager
。除了应用程序之外,它不接收任何其他参数。
- 烧瓶登录。user_needs_refresh
-
needs_refresh
当在 .上调用该方法时发送LoginManager
。除了应用程序之外,它不接收任何其他参数。
- 烧瓶登录。session_protected
-
每当会话保护生效时发送,并且会话被标记为非新鲜或已删除。除了应用程序之外,它不接收任何其他参数。

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了