我有一个金字塔项目,有两个部分:
/_hq/
需要通过登录页面进行身份验证/_rest/
需要RESTful身份验证(通过HTTP基本/摘要式身份验证)所以,我添加了2个主要资源工厂的路由: HQFactory 和 RESTFactory 。我已经构建了一个身份验证策略切换器来切换每个资源的AuthenticationPolicy。它奏效了。
我也使用ACLAuthorizationPolicy。
对于每个请求,我想返回登录页面或 401 HTTP状态取决于正在访问的资源工厂。
我的问题是我只能为一个视图执行 @forbidden_view_config 。如何为每个资源工厂或其他解决方案指定出价问题?
谢谢
最简单的方法是Michael Merickel的回答(你可以在下面看到)。还有另一种方式:
已过时
我通过使用来自view_config的custom_predicates arg解决了我的问题。就是这样。
我创建了一个自定义谓词函数:
def resource_factory_predicate(factory):
def check_factory(context, request):
return isinstance(request.context, factory)
return check_factory
然后,这是我的views.py
# views.py
@forbidden_view_config(
custom_predicates=(resource_factory_predicate(RootFactory),))
def login_required(request):
userid = authenticated_userid(request)
if userid is not None:
return HTTPForbidden("You're not authorized for this action")
# redirect to login page
@forbidden_view_config(renderer='json',
custom_predicates=(resource_factory_predicate(RESTfulFactory),))
def http_403_unauthenticated(request):
request.response.status = 403
return {
'status': 0,
'message': 'Forbidden',
}
答案 0 :(得分:2)
虽然您无法根据上下文调度异常视图(该异常用作上下文),但可以欺骗并使用containment
选项,该选项要求指定的类型位于{{3}中实际的背景。这意味着如果它下面的任何上下文引发异常,它也将匹配,从而影响遍历层次结构的整个子树。
@forbidden_view_config(containment=MyRootA)
def root_a_forbidden(exc, request):
# note that the actual context is available on request.context
pass
@forbidden_view_config(containment=MyRootB)
def root_b_forbidden(exc, request):
pass
答案 1 :(得分:1)
禁止观点与其他观点一样,真的;请参阅@forbidden_view_config()
decorator documentation:
pyramid.view.view_config
的类似物,用于注册禁止的视图。
forbidden_view_config
构造函数接受与pyramid.view.view_config
的构造函数大多数相同的参数。它可以在相同的地方使用,并且行为大致相同,只是它总是注册一个禁止的异常视图而不是“普通”视图。
这意味着它接受与pyramid.view.view_config()
相同的谓词;装饰器基本上调用add_forbidden_view()
,这意味着它的参数可以在装饰器中使用;该方法的文档明确排除context
,但路由名称 是一个选项:
@forbidden_view_config(route_name='hq'):
def forbidden_for_hq(request):
# ...
@forbidden_view_config(route_name='rest'):
def forbidden_for_rest(request):
# ...
如果要映射的路线太多,请考虑使用custom predicate。您已经拥有自定义身份验证策略切换器;您需要做的就是添加一个自定义谓词,该谓词将检测正在使用的策略。