Python 检查当前用户是否具有金字塔服务的权限?

Python 检查当前用户是否具有金字塔服务的权限?,python,acl,pyramid,cornice,Python,Acl,Pyramid,Cornice,我使用檐口和金字塔与ACL认证。这是一个复制品,我在问金字塔已经改变了 假设pyramid.security.has_permission已替换为request.has_permission,该请求具有可选的上下文参数。我试图在所有服务中循环使用has_permission,以查看当前用户(请求)可以访问哪些服务 最终目标是动态扫描所有檐口服务(即使用檐口的@resourcedecorator查看文件),以查看哪些文件获得了当前用户给定权限(即'view')的授权。除了拥有_权限之外,我还愿意使

我使用檐口和金字塔与ACL认证。这是一个复制品,我在问金字塔已经改变了

假设
pyramid.security.has_permission
已替换为
request.has_permission
,该请求具有可选的
上下文
参数。我试图在所有服务中循环使用
has_permission
,以查看当前用户(
请求
)可以访问哪些服务

最终目标是动态扫描所有檐口服务(即使用檐口的
@resource
decorator查看文件),以查看哪些文件获得了当前用户给定权限(即
'view'
)的授权。除了
拥有_权限
之外,我还愿意使用另一种方法

此知识的用例是提供一个Swagger Spec JSON文档,该文档仅记录当前用户可用的API端点

我希望代码看起来像这样:

from cornice import service
# Get our list of services
services = service.get_services()
# Assume we have an authenticated user logged in, thus attaching auth info to request
for svc in services:
    context = magic_context_function(svc)
    if request.has_permission('view', context) == False:
        # Code will go here to hide endpoint documentation for this endpoint

答案似乎应该是使用,但我无法让它使用任意视图名称,因为
名称
arg与
檐口.service.name
值不匹配

然而,这里有一个来自a的半解。您将需要一些导入来使链接的解决方案工作(更好)。这是完整的代码

from pyramid.security import _get_registry, Allowed
from pyramid.interfaces import IRouteRequest, IRequest, IViewClassifier, ISecuredView, IView
from zope.interface import providedBy
def route_view_execution_permitted(context, request, route_name, name=''):
    reg = _get_registry(request)
    context_iface = providedBy(context)
    request_iface = reg.queryUtility(
        IRouteRequest,
        name=route_name,
        default=IRequest)
    provides = (IViewClassifier, request_iface, context_iface)

    view = reg.adapters.lookup(provides, ISecuredView, name=name)
    if view is None:
        view = reg.adapters.lookup(provides, IView, name=name)
        if view is None:
            raise TypeError('No registered view satisfies the constraints. '
                            'It would not make sense to claim that this view '
                            '"is" or "is not" permitted.')
        return Allowed(
            'Allowed: view name %r in context %r for route %r (no permission defined)' %
            (name, context, route_name))
    return view.__permitted__(context, request)
可以使用上述功能来确定当前用户(根据
请求
对象确定)是否能够访问服务(按名称),如下所示:

我发现上述解决方案有两个缺陷:

  • 这很慢,因为由于某种原因,
    svc
    循环的每次迭代都会打开到API的新连接
  • 它返回一个错误的结果(即说一个人对他没有权限的服务有权限,反之亦然)
  • 也许有人能找到一种改进上述答案的方法。同时,这里有一个解决方案,使用附加到每个服务的ACL,然后确定当前的
    请求.effective\u主体是否匹配

    # Now see if current user meets ACL requirements for any permission
    is_permitted = None  # set our default.
    for ace in acl:
        for principal in request.effective_principals:
            if ace[1] == principal:
                is_permitted = True if ace[0] == Allow else False
                break
        if is_permitted is not None:
            break
    
    if is_permitted is True:
        # Do something interesting...
    
    这里的弱点是:

  • 它的速度很慢,原因与前面的解决方案相同
  • 在实现时,它只查看
    @resource
    -修饰的服务类,而不查看
    @view
    -修饰的方法,这些方法可能具有自己的权限或ACL 这可以通过以下方式进行补救:

    for method, view, args in service.definitions:
        if 'permission' in args:
            # Now start looking at permission to see if they match what's given by the parent ACL in the resource class
            # Also, the special "__no_permission_required__" value means we should not have a Security Requirement Object
            if args['permission'] == NO_PERMISSION_REQUIRED :
                # Interesting....
    
    for method, view, args in service.definitions:
        if 'permission' in args:
            # Now start looking at permission to see if they match what's given by the parent ACL in the resource class
            # Also, the special "__no_permission_required__" value means we should not have a Security Requirement Object
            if args['permission'] == NO_PERMISSION_REQUIRED :
                # Interesting....