检查当前用户是否有传销服务权限?
Check if current user has permission for pyramid service?
我将 Cornice 和 Pyramid 与 ACL Auth 一起使用。这是 older question 的副本,因为 Pyramid 已更改,我正在重新询问。
Current docs 表示 pyramid.security.has_permission
已替换为 request.has_permission
,后者具有可选的 context
arg。我试图在所有服务的循环中使用 has_permission
来查看当前用户 (request
) 可以访问哪些服务。
最终目标是动态扫描所有 Cornice 服务(即使用 Cornice 的 @resource
装饰器查看文件)以查看当前用户哪些服务被授予给定权限(即 'view'
) .除了 has_permission
之外,我愿意使用另一种方式来做到这一点。
此知识的用例是提供 Swagger 规范 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
似乎答案应该是使用 view_execution_permitted(context, request, name=''),但我无法让它与任意视图名称一起使用,因为 name
arg 与 [=15] 不匹配=] 值。
但是,这是来自 Pyramid issue on Github 的半解决方案。您将需要一些导入以使链接的解决方案工作(更好)。这是完整的代码
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)
可以使用上述函数来确定当前用户(由 request
对象确定)是否能够访问服务(按名称),如下所示:
from cornice import service
services = service.get_services()
for svc in services:
view_permitted = route_view_execution_permitted(request.context, request, svc.name)
if view_permitted == True:
# Do something interesting...
我发现上面的方案有两个不足:
- 它很慢,因为
svc
循环的每次迭代都会出于某种原因打开到 API 的新连接。
- 它 returns 一个错误的结果(即说一个人有权使用他没有的服务,反之亦然)
也许有人可以看到改进上述答案的方法。同时,这里有一个解决方案,使用附加到每个服务的 ACL,然后确定当前 request.effective_principals
是否匹配。
# 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....
我将 Cornice 和 Pyramid 与 ACL Auth 一起使用。这是 older question 的副本,因为 Pyramid 已更改,我正在重新询问。
Current docs 表示 pyramid.security.has_permission
已替换为 request.has_permission
,后者具有可选的 context
arg。我试图在所有服务的循环中使用 has_permission
来查看当前用户 (request
) 可以访问哪些服务。
最终目标是动态扫描所有 Cornice 服务(即使用 Cornice 的 @resource
装饰器查看文件)以查看当前用户哪些服务被授予给定权限(即 'view'
) .除了 has_permission
之外,我愿意使用另一种方式来做到这一点。
此知识的用例是提供 Swagger 规范 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
似乎答案应该是使用 view_execution_permitted(context, request, name=''),但我无法让它与任意视图名称一起使用,因为 name
arg 与 [=15] 不匹配=] 值。
但是,这是来自 Pyramid issue on Github 的半解决方案。您将需要一些导入以使链接的解决方案工作(更好)。这是完整的代码
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)
可以使用上述函数来确定当前用户(由 request
对象确定)是否能够访问服务(按名称),如下所示:
from cornice import service
services = service.get_services()
for svc in services:
view_permitted = route_view_execution_permitted(request.context, request, svc.name)
if view_permitted == True:
# Do something interesting...
我发现上面的方案有两个不足:
- 它很慢,因为
svc
循环的每次迭代都会出于某种原因打开到 API 的新连接。 - 它 returns 一个错误的结果(即说一个人有权使用他没有的服务,反之亦然)
也许有人可以看到改进上述答案的方法。同时,这里有一个解决方案,使用附加到每个服务的 ACL,然后确定当前 request.effective_principals
是否匹配。
# 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....