为Authorization编写CherryPy装饰器
我有一个使用cherrypy的应用程序,在某些页面上,我想只允许特定的用户查看这些页面,其他人则需要被引导到一个需要授权的页面。
有没有办法通过自定义装饰器来实现这个功能?我觉得这样做会是最优雅的选择。
下面是我想要实现的一个基本示例:
class MyApp:
@authorization_required
def view_page1(self,appID):
... do some stuff ...
return html
def authorization_required(func):
#what do I put here?
另外,当调用authorization_required这个函数作为装饰器时,能否接受像allow_group1、allow_group2这样的参数?还是说我需要为每个组创建一个单独的装饰器?
2 个回答
15
你其实不想为CherryPy写自定义装饰器。相反,你应该写一个新的工具:
def myauth(allowed_groups=None, debug=False):
# Do your auth here...
authlib.auth(...)
cherrypy.tools.myauth = cherrypy.Tool("on_start_resource", myauth)
想了解更多,可以看看这个链接:http://docs.cherrypy.org/en/latest/extend.html#tools。使用工具相比于写自定义装饰器有几个好处:
- 你可以直接从工具中获得装饰器,比如:
@cherrypy.tools.myauth(allowed_groups=['me'])
,而且它已经知道怎么处理和同一个函数的cherrypy.exposed不冲突。 - 你可以根据需要在不同的地方使用工具,比如针对每个处理器(用装饰器)、针对每个控制器树(通过
_cp_config
)或者针对每个URI树(在配置文件或字典中)。你甚至可以把它们混合使用,先通过装饰器提供基本功能,然后在配置文件中覆盖它们的行为。 - 如果配置文件把你的功能关掉了,你就不用担心调用装饰器函数的性能损失,因为它根本不会被调用。
- 你会记得像所有内置工具那样添加一个'debug'参数。;)
- 你的功能可以在比自定义装饰器更早(或更晚,如果你需要的话)的时候运行,因为你可以选择不同的“时机”。
- 如果需要的话,你的功能可以在多个钩子点运行。
4
好的,在这种情况下,你的装饰器大概会是这样的:
# without any parameters
def authentication_required(f):
@functools.wraps(f)
def _authentication_required(*args, **kwargs):
# Do you login stuff here
return f(*args, **kwargs)
return _authentication_required
# With parameters
def authentication_required(*allowed_groups):
def _authentication_required(f):
@functools.wraps(f)
def __authentication_required(*args, **kwargs):
# Do you login stuff here
return f(*args, **kwargs)
return __authentication_required
return _authentication_required