金字塔 - 如何配置多个禁止视图取决于资源工厂?

时间:2013-07-16 10:35:15

标签: authentication pyramid

我有一个金字塔项目,有两个部分:

  • /_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',
    }

2 个答案:

答案 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。您已经拥有自定义身份验证策略切换器;您需要做的就是添加一个自定义谓词,该谓词将检测正在使用的策略。