我已经实现了一个具有一些复杂授权要求的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来集中访问控制。我必须保护以下网址
我的应用程序充满了每个REST资源的复杂授权要求,我想使用自定义org.springframework.security.access.PermissionEvaluator,特别是通过实现以下方法。
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)
我打算使用targetType和request.getUrl()的组合来为每个url和资源获取一个专门的Evaluator。 有更好的方法吗?
答案 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元组,但这是一个实际的细节,经验丰富的弹簧用户可以理解。