Ответ 1
Я знаю, что этот вопрос старый, но пару дней назад я искал то же самое, поэтому, надеюсь, это поможет кому-то в будущем.,
Хорошее место для начала - репозиторий github для Flask-Principal.
У меня были проблемы с Flask-Principal (FP). Если вы новичок в decorators, контекстных менеджерах и , вы, вероятно, захотите изучить их немного перед использованием FP.
Колба регистрирует сигналы на основе пакета Blinker. Если у вас нет Blinker, Flask все равно позволит вам объявлять сигналы, однако ничего не сделает. Чтобы понять, что я имею в виду, посмотрите в источник для Flask signals.py.
Так почему это имеет значение для FP? Ну, оказывается, что FP использует сигналы для регистрации и обновления идентификаторов. В частности:
-
identity_loaded
: Когда этот сигнал вызывается, нам известно создать объект идентификации для пользователя. (Он называется черезPrincipal._set_thread_identity()
) -
identity_changed
: Когда этот сигнал вызывается, нам известно обновить идентификатор пользователя. (Когда он называется выполняетPrincipal._on_identity_changed()
)
Итак, что я имею в виду под названием? Во-первых, нам нужно знать, как настроены сигналы. Blinker работает, позволяя функциям "подписаться" на сигналы. Так, например, Principal._on_identity_changed()
настроен как абонент для сигнала identity_changed
. Всякий раз, когда посылается сигнал identity_changed
, выполняется _on_identity_changed(). Код выглядит следующим образом:
from blinker import signal
test = signal('test')
test.connect(func_we_want_to_execute_when_signal_is_called)
Вернемся к вопросу о том, как вызываются сигналы. В Blinker обработчики сигналов выполняются, когда мы вызываем send()
на объект сигнала. Итак, для нашего сигнала test
синтаксис справедлив:
test.send()
Когда test.send()
вызывается func_we_want_to_execute_when_signal_is_called
, выполняется. Надеюсь, этот пример в документации FP теперь немного больше имеет смысл:
def login_view(req):
username = req.form.get('username')
# Your authentication here.
# Notice our signal (identity_changed) is being called (identity_changed.send())
# What function is being called? Principal._on_identity_changed()
identity_changed.send(app, identity=Identity(username))
Однако мы можем упростить настройку сигналов, если мы используем декоратор, чтобы сделать это для нас. Притворись еще раз, что я установил свой тестовый сигнал, но не подключил его. Мы можем сделать:
@test.connect
def func_we_want_to_execute_when_signal_is_called():
return stuff
Что делает вышеприведенный код, по существу устанавливает функцию, которую мы хотим выполнить при отправке нашего тестового сигнала. Надеюсь, теперь следующий код из документации FP имеет смысл:
# We're setting up our signal (identity_loaded)
# to execute the function below (on_identity_loaded)
# when we call our signal (identity_loaded.send())
# which is called in Principal._set_thread_identity()
@identity_loaded.connect
def on_identity_loaded(sender, identity):
# Get the user information from the db
user = db.get(identity.name)
# Update the roles that a user can provide
for role in user.roles:
identity.provides.add(RoleNeed(role.name))
# Save the user somewhere so we only look it up once
identity.user = user
Итак, вы можете видеть, что сигналы действительно управляют процессом идентификации. Роли и разрешения действительно (более легкие) запоздалые мысли, если вы ищете способ сделать авторизацию любого рода.
Для меня обертывание головы вокруг сигналов было самой сложной частью; Надеюсь, это тоже помогло кому-то другому. Но я действительно рекомендую вам прочитать исходный код, который я связал выше для Flask-Principal; это, вероятно, будет лучшим способом понять, что происходит.