如何使用多个蓝图处理登录瓶?

And*_*tra 7 python flask flask-login

我有多个蓝图需要集成到一个应用程序中.我正在使用flask-login登录.但是我对如何处理LoginManager().user_loader我的蓝图感到困惑.

这是我目前的文件结构.

system/
     run.py
     config.py
     app/
        __init__.py
        models.py
        views/
             blueprint1.py
             blueprint2.py
        static/
        templates/
              <templates>
Run Code Online (Sandbox Code Playgroud)

实施它们的正确方法是什么?我只是在它上面调用它们__init__.py并在蓝图中导入登录管理器变量吗?或者我是否需要在蓝图中单独调用它们?

希望我能够清楚地描述这个问题.感谢您阅读和回答

tbi*_*icr 8

您必须明白,对于一个应用程序,无论您使用多少蓝图,您都必须使用一个登录管理器(当然,例如当蓝图是独立的时,可能会有特定的例外情况,但在这种情况下您可能无法使用flask-login).因为:

  1. 你有1个入口点
  2. 如果用户未登录,他将被重定向到登录/注册页面
  3. 你有1个用户加载器

登录管理器如何工作:

  1. current_user在请求上下文中注册
  2. before_request读取您的会话,获取用户ID,加载用户user_loader并将其设置为current_userAnonymousUser
  3. 当您访问私人页面时,login_required检查current_user.is_authenticated()其他重定向到登录页面
  4. 登录时,它会向会话添加用户ID

所以,你必须初始化只有一个烧瓶应用登录管理器实例,然后使用login_requiredcurrent_user您的所有蓝图.


Abh*_*pta 5

这就是我处理它的方式:

这是我初始化一切的地方:

import logging
import logging.config

import flask
import flask.globals as flask_global
import flask_login

from config import flask as flask_config
from rest.api import dashboard
from rest.api.util import login_decorator

logger = logging.getLogger(__name__)

# app
flask_app = flask.Flask(__name__)
flask_app.config.from_object(flask_config)

# login manager needs be set before blueprint registration
login_manager = flask_login.LoginManager()
login_manager.init_app(flask_app)

flask_app.register_blueprint(dashboard.blueprint)


# setting blueprint specific login view
# login_manager.login_view = "login"


@login_manager.user_loader
def load_user(user_id):
    """
    This will be used many times like on using current_user
    :param user_id: username
    :return: user or none
    """
    # http://librelist.com/browser/flask/2012/4/7/current-blueprint/#44814417e8289f5f5bb9683d416ee1ee
    blueprint = flask_global.current_app.blueprints[request.blueprint]

    if hasattr(blueprint, load_user):
        return blueprint.load_user(user_id)

    # https://flask-login.readthedocs.org/en/latest/#how-it-works
    return None
Run Code Online (Sandbox Code Playgroud)

这是我的蓝图,它有自己的登录处理:

from __future__ import absolute_import

import flask
import flask_login
from flask import Blueprint

from core.models.profile import Agent
from core.utils import thread_local
from rest.api.util import login_decorator

blueprint = Blueprint('human', __name__, url_prefix='/human')


def load_user(user_id):
    """
    This will be used many times like on using current_user
    :param user_id: username
    :return: user or none
    """
    agent = None
    try:
        agent = Agent.objects.get(username=user_id)
    except:
        # https://flask-login.readthedocs.org/en/latest/#how-it-works
        pass
    return agent


@blueprint.record_once
def on_load(state):
    """
    http://stackoverflow.com/a/20172064/742173

    :param state: state
    """
    blueprint.load_user = load_user
    state.app.login_manager.blueprint_login_views[blueprint.name] = 'human.login'


@blueprint.route('/login', methods=['POST'])
@login_decorator.login_not_required
def login():
    username = flask.request.args.get('username')
    password = flask.request.args.get('password')
    try:
        agent = Agent.objects.get(username=username)
    except:
        return 'Invalid username'

    if not agent.check_password(password):
        return 'Invalid password'

    flask_login.login_user(agent)

    return 'Valid login'


@blueprint.route("/logout")
def logout():
    flask_login.logout_user()
    return 'Logout done'


@blueprint.before_request
def before_request():
    agent = flask_login.current_user
    # https://flask-login.readthedocs.org/en/latest/#anonymous-users
    is_logged_in = agent.get_id() is not None

    login_not_required = getattr(flask.current_app.view_functions[flask.request.endpoint], 'login_not_required', False)
    is_static_resource_call = flask.request.endpoint.startswith('static/')

    if is_static_resource_call or is_logged_in or login_not_required:
        if is_logged_in:
            thread_local.set_current_brand_id(agent.brand_id)
    else:
        flask.abort(401)
        # if we want to redirect to some page then we can use this. The appropriate login_view should be set
        # return flask.current_app.login_manager.unauthorized()
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.