2

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

  • /_hq/需要通过登录页面进行身份验证
  • /_rest/需要 RESTful 身份验证(通过 HTTP 基本/摘要式身份验证)

因此,我添加了带有 2 个主要资源工厂的路由:HQFactoryRESTFactory。我已经构建了一个身份验证策略切换器来切换每个资源的 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',
    }
4

2 回答 2

3

虽然您不能根据上下文调度异常视图(异常用作上下文),但可以作弊并使用containment要求指定类型位于lineage实际上下文中的选项。这意味着如果它下面的任何上下文引发异常,它也会匹配,从而影响遍历层次结构的整个子树。

@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
于 2013-07-16T16:09:13.647 回答
1

禁见与其他任何见一样,真的;请参阅@forbidden_view_config()装饰器文档

一个类似物pyramid.view.view_config注册了一个禁止的视图

构造函数接受大多数与的forbidden_view_config构造函数相同的参数pyramid.view.view_config。它可以在相同的地方使用,并且行为方式大致相同,除了它总是注册一个禁止的异常视图而不是“正常”视图。

这意味着它接受与 dos 相同的谓词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):
    # ...

如果要映射的路线太多,请考虑使用自定义谓词。您已经拥有自定义身份验证策略切换器;您需要做的就是添加一个自定义谓词,该谓词将检测正在使用的策略。

于 2013-07-16T10:41:19.800 回答