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 重新加载用户对象。它应该获取用户的strID,并返回相应的用户对象。例如:

@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

True如果这是匿名用户,则应返回此属性。(实际用户应该返回False。)

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_NEXTis 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=Truelogin_user 调用。cookie 将保存在用户的计算机上,如果不在会话中,Flask-Login 将自动从该 cookie 中恢复用户 ID。cookie 过期前的时间量可以通过 REMEMBER_COOKIE_DURATION配置设置,也可以传递给login_usercookie 是防篡改的,因此如果用户篡改它(即插入其他人的用户 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_viewneeds_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 的详细信息。

REMEMBER_COOKIE_NAME

存储“记住我”信息的 cookie 的名称。默认值: remember_token

REMEMBER_COOKIE_DURATION

cookie 过期之前的时间量,作为datetime.timedelta对象或整数秒。 默认值: 365 天(1 个非闰公历年)

REMEMBER_COOKIE_DOMAIN

如果“记住我”cookie 应该跨域,请在此处设置域值(即.example.com 允许 cookie 用于 的所有子域example.com)。 默认: None

REMEMBER_COOKIE_PATH

将“记住我”cookie 限制为特定路径。 默认: /

REMEMBER_COOKIE_SECURE

将“记住我”cookie 的范围限制为安全通道(通常是 HTTPS)。 默认: False

REMEMBER_COOKIE_HTTPONLY

防止客户端脚本访问“记住我”cookie。 默认: True

REMEMBER_COOKIE_REFRESH_EACH_REQUEST

如果设置为True每次请求都会刷新 cookie,这会影响生命周期。像 Flask 一样工作SESSION_REFRESH_EACH_REQUEST。 默认: False

REMEMBER_COOKIE_SAMESITE

将“记住我”cookie 限制为第一方或同一站点上下文。 默认: None

会话保护

虽然上述功能有助于保护您的“记住我”令牌免受 cookie 窃贼的侵害,但会话 cookie 仍然容易受到攻击。Flask-Login 包括会话保护,以帮助防止用户的会话被盗。

LoginManager您可以在, 和应用程序的配置中配置会话保护。如果启用,它可以在任一basicstrong 模式下运行。要将其设置在 上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_loginbool, 默认为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(),那么它将被调用。否则,它将采取以下措施:

  • LoginManager.login_message给用户。

  • 如果应用程序正在使用蓝图,则使用 .找到当前蓝图的登录视图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未定义,那么它将简单地引发 HTTP 401(未经授权)错误。

这应该从视图或 before/after_request 函数返回,否则重定向将无效。

常规配置

user_loader (回调)[资源]

这设置了从会话重新加载用户的回调。您设置的函数应采用用户 ID (a str) 并返回用户对象,或者None如果用户不存在。

参数

callback ( callable ) -- 用于检索用户对象的回调。

request_loader (回调)[资源]

这设置了从 Flask 请求加载用户的回调。您设置的函数应该接受 Flask 请求对象并返回一个用户对象,或者None如果用户不存在。

参数

callback ( callable ) -- 用于检索用户对象的回调。

匿名

产生匿名用户的类或工厂函数,在无人登录时使用。

unauthorized配置

登录视图

用户需要登录时重定向到的视图的名称。(如果您的身份验证机制在您的应用程序之外,这也可以是绝对 URL。)

blueprint_login_views

这类似于 login_view,除了在处理蓝图时使用。它是一个字典,可以存储多个视图以重定向到不同的蓝图。重定向以键的形式列出,作为蓝图的名称,值作为重定向到路由。

登录信息

当用户被重定向到登录页面时闪烁的消息。

未授权处理程序回调[资源]

这将为该unauthorized方法设置回调,其中包括login_required它不接受任何参数,并且应该返回要发送给用户的响应,而不是他们的正常视图。

参数

callback ( callable ) -- 未授权用户的回调。

needs_refresh配置

刷新视图

用户需要重新验证时重定向到的视图的名称。

需求刷新消息

当用户被重定向到重新认证页面时闪烁的消息。

needs_refresh_handler (回调)[资源]

这将为该needs_refresh方法设置回调,其中包括fresh_login_required它不接受任何参数,并且应该返回要发送给用户的响应,而不是他们的正常视图。

参数

callback ( callable ) -- 未授权用户的回调。

登录机制

烧瓶登录。用户¶

当前用户的代理。

烧瓶登录。登录刷新)[资源]

True如果当前登录是新的,则返回。

烧瓶登录。login_remembered ( )[资源]

True如果跨会话记住当前登录,则返回。

烧瓶登录。login_user用户记住=持续时间=强制=新鲜=[资源]

登录用户。您应该将实际的用户对象传递给它。如果用户的is_active属性是,除非False,否则他们将不会登录forceTrue

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 指南,HTTPOPTIONS请求免于登录检查。

参数

func ( function ) -- 要装饰的视图函数。

烧瓶登录。fresh_login_required (函数)[资源]

如果你用它来装饰视图,它将确保当前用户的登录是新鲜的——即他们的会话不是从“记住我”cookie 中恢复的。敏感操作,如更改密码或电子邮件,应该受到保护,以阻止 cookie 窃贼的努力。

如果用户未通过身份验证,LoginManager.unauthorized()则正常调用。如果他们经过身份验证,但他们的会话不是新鲜的,它将调用LoginManager.needs_refresh()(在这种情况下,您需要提供LoginManager.refresh_view.)

就配置变量而言,其行为与login_required()装饰器相同。

笔记

根据CORS 预检请求的 W3 指南,HTTPOPTIONS请求免于登录检查。

参数

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. If next_url is provided, however, this will append a next=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, set FORCE_HOST_FOR_REDIRECTS to a host. This prevents from redirecting to external sites if request headers Host or X-Forwarded-For are present.

Parameters
  • login_view (str) – The name of the login view. (Alternately, the actual URL to the login view.)

  • next_url (str) – The URL to give the login view for redirection.

  • next_field (str) – What field to store the next URL in. (It defaults to next.)

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

每当会话保护生效时发送,并且会话被标记为非新鲜或已删除。除了应用程序之外,它不接收任何其他参数。

 
 
在 GitHub 上叉我
  五:最新 
posted @   菩提浪子  阅读(363)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示

目录导航