Flask-principal 教程(认证 + 授权)

29 投票
3 回答
21762 浏览
提问于 2025-04-16 23:31

有人知道关于flask-principal的好教程吗?我想做身份验证和授权(需要角色和身份),但是一直没有头绪。

我几乎可以肯定没有特别全面的教程——也许你们中有些人有时间,可以把教程作为回答发出来?我真的很想用flask,而不是django,但需要先解决这个问题。

3 个回答

6

不知道为什么,网上关于Flask-Principal的例子非常少。我个人觉得Flask-Principal的文档一开始看起来很难懂。不过,当我查看源代码后,感觉一切都变得清晰多了。

受到我找到的这两个链接的启发,这里这里,我整理了一个简单的例子,使用了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感兴趣,它提供了会话管理的功能,这个在之前提到的博客中也有介绍。

这里可能没有人有相关的经验(并且有时间详细分享),但我非常支持把教程作为答案。

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的源代码;这可能是理解发生了什么的最佳方式。

撰写回答