Flask-principal教程(身份验证+授权)

29

有没有关于flask-principal的好教程?我正在尝试进行身份验证和授权(需求角色和需求身份),但是一无所获。

我几乎可以肯定没有真正全面的教程--也许你们中的一些人有时间并想发布一个教程作为答案?我非常决心使用flask而不是django,但需要解决这个问题。


@InnocentPixel,你最终选择了什么/在这里学到了什么,有什么评论吗?谢谢! - Jeff
@Jeff 看起来有人发布了一个不错的教程作为答案! - agf
这里也有一个(https://github.com/saltycrane/flask-principal-example),也已经过了几年...... - scharfmn
3个回答

52
我知道这个问题有点老了,但是几天前我也在寻找同样的东西,希望这能帮助将来的某个人......一个很好的起点是Flask-Principal的Github仓库。我也遇到了一些与Flask-Principal (FP)有关的问题。如果你对装饰器上下文管理器信号不熟悉,那么在使用FP之前,你可能需要对它们进行一些研究。Flask基于一个叫做Blinker的包注册信号。如果你没有Blinker,Flask仍然允许你声明信号,但是它们不会执行任何操作。要了解我的意思,请查看Flask的signals.py源代码。
因此,这对FP有什么影响呢?事实证明,FP使用信号来注册和更新身份。具体来说:
  1. identity_loaded:当调用此信号时,我们知道要为用户创建一个身份对象。(通过Principal._set_thread_identity()调用)

  2. 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源代码; 这可能是了解正在发生什么的最佳方法。

尽管我仍然不太清楚,但我真的很感激你的意图和努力。 - userx

6
由于某种原因,关于Flask原理的示例非常少。我个人发现Flask-Principal文档一开始就很难懂。一旦我阅读了源代码,一切似乎都更加清晰了。
受到这两个链接的启发,链接如下:herehere,我使用flask-login、flask-principals和蓝图组合编写了一个简单的示例。
您可以在此处找到示例:https://github.com/shankararul/flask-login-principal 我尽力在本文中进行解释。如果您有任何反馈,请告诉我,我可以修改/更新本文。
此外,您还可以在此处找到更多信息:https://medium.com/@shankararul/a-shot-at-demystifying-flask-principal-dda5aaeb6bc6

6
目前唯一的相关内容似乎是这篇博客文章。项目的网站提供了一个简短的教程,后面是完整的API文档。你的问题表明你已经看过了这些内容。你可能也会对flask-login感兴趣,它提供了会话管理,并在链接的博客文章中有介绍。虽然这里没有人有相关经验(并且有时间详细分享),但我支持将其作为教程回答。

我看了那个教程,但还是觉得不够(我仍然对这方面的知识了解有限)。Flask-Login 只提供登录功能,我希望还能实现授权功能(需要角色和身份验证)。我打算在网站和 REST API 中使用它,并且 REST API 也需要进行授权。另外,使用服务器端会话来确保 API 仅对注册用户开放也是一个好主意。是的,我看过项目的网站,但我想找一个详细的指导,以填补我知识上的空白。 - pocorschi
1
是的,不幸的是,我认为目前没有这样的东西。我的唯一建议是定期编辑帖子添加更多信息(这会将其推到“活动”选项卡上,但不要仅仅为了推)。如果您在两天内没有得到好的答案,您可以向问题添加赏金,以便将其添加到“特色”选项卡中,并希望您能与想要学习的人或曾经使用过它的人有所运气。 - agf
谢谢agf的鼓励,我一定会去做的。 - pocorschi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接