自定义PermissionEvaluator,用于为每个REST资源授权资源访问

时间:2016-01-06 04:07:38

标签: java spring rest spring-security acl

我已经实现了一个具有一些复杂授权要求的REST应用程序。

以下是摘要

我的客户购买了一个名为Collector的代理设备,可以集中管理家庭自动化控制。我的客户还购买了多个家庭自动化设备(我们称之为HADevices),通过收集器向我的REST应用程序报告他们的指标。

具有角色ROLE_ADMIN的管理员(谁是我的客户服务代表)应该能够查看来自任何收集器或HADevice的任何数据。具有角色ROLE_USER角色的客户应该只能查看有关收集器或其拥有的HADevice的数据。

具有角色ROLE_COLLECTOR的收集器是唯一有权插入数据的角色,即在我的REST服务中创建或更新资源。我们称之为url / deviceMetrics(POST)。收集器可以插入与客户关联的任何HADevice的度量标准。 HADevices没有角色,也没有与我的REST应用程序交互。收集器只能将记录插入与收集器具有相同客户的HADevices。

我使用spring security 4.0进行身份验证,使用@Secured注释进行授权。但是,我发现我的代码混乱了重复的权限验证,占用了我的大部分逻辑。基本的插入和检索非常简单。

我想使用PermissionEvaluator来集中访问控制。我必须保护以下网址

  • GET / collectors / {id} / deviceMetrics - 我从中检索用户 在我的春天,校长并验证id = {id}的收集器 数据存储库属于Principal,如果不是,我发送403
  • GET / hadevices / {id} / deviceMetrics - 我从中检索用户 在我的spring数据中建立并验证id = {id}的HADevice 存储库属于Principal,如果不是,我发送403.
  • POST / collectors / {id} / deviceMetrics - 我检索收集器uniqueId 来自校长,并确保收藏家的ID与 URL中的{id}
  • POST / hadevice / {id} / deviceMetrics - 我检索了 收集者uniqueId来自委托人和相关客户。一世 还会将与HADevice关联的客户拉为id = {id}和 比较两者。如果他们不平等,我发送403。

我的应用程序充满了每个REST资源的复杂授权要求,我想使用自定义org.springframework.security.access.PermissionEvaluator,特别是通过实现以下方法。

boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)

我打算使用targetType和request.getUrl()的组合来为每个url和资源获取一个专门的Evaluator。 有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

你的问题相当广泛,但我认为你可以在大多数情况下使用非常简单的逻辑。

  

GET / collectors / {id} / deviceMetrics

鉴于您有一个具有合适属性的DeviceMetrics类,您可以使用以下内容注释数据存储库:

@PostAuthorize("hasRole('ROLE_ADMIN') or (hasRole('ROLE_USER') and returnObject.collector.owner = authentication.name)")
public DeviceMetrics getDeviceMetrics(long deviceId);

(这假定DeviceMetrics类的属性collector具有属性owner,即用户名。)

根本不需要PermissionEvaluator。也许你需要一个更复杂的案例:

  

POST / collectors / {id} / deviceMetrics

@PreAuthorize("hasRole('ROLE_COLLECTOR') and hasPermission(#collectorId, 'com.example.Collector', 'WRITE')")
public void saveDeviceMetrics(long collectorId, DeviceMetrics deviceMetrics);

您只需要一个 PermissionEvaluator,因为您获得了所需的所有信息作为方法参数。

答案 1 :(得分:0)

对于那些想知道我的解决方案是什么样子的人,我借用this示例。

这是旧的,它基于xml配置,我不是特别喜欢。但我们的想法是创建一个Map并初始化自定义PermissionValidator并将授权逻辑存储在Permission接口实现中。

最大的痛点在于注入一个自动连接的HashMap元组,但这是一个实际的细节,经验丰富的弹簧用户可以理解。