Flask-principal 教程(认证 + 授权)
有人知道关于flask-principal的好教程吗?我想做身份验证和授权(需要角色和身份),但是一直没有头绪。
我几乎可以肯定没有特别全面的教程——也许你们中有些人有时间,可以把教程作为回答发出来?我真的很想用flask,而不是django,但需要先解决这个问题。
3 个回答
不知道为什么,网上关于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
目前好像只有这篇博客提到过相关内容。
这个项目的网站上有一个(非常简短的)教程,后面还有完整的API文档。你的问题表明你已经看过这些内容了。
你可能还会对flask-login感兴趣,它提供了会话管理的功能,这个在之前提到的博客中也有介绍。
这里可能没有人有相关的经验(并且有时间详细分享),但我非常支持把教程作为答案。
我知道这个问题有点老了,但几天前我也在找同样的东西,希望这能帮助到未来的某个人……
一个好的起点是去看看Flask-Principal的GitHub仓库。
我在使用Flask-Principal(FP)时也遇到了一些问题。如果你对装饰器、上下文管理器和信号不太熟悉,建议你在使用FP之前先了解一下这些概念。
Flask是通过一个叫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的源代码;这可能是理解发生了什么的最佳方式。