3.9.8. 集合属性的安全约束

考虑下面这个情况:

  • 数据模型包含 OrderOrderLine 实体,形成了一对多的关系。

  • REST 客户端获取了一个 Order 实例,并且带着嵌套的 OrderLine 实例集合。

  • 有些安全约束可以过滤掉某些 OrderLine 实例,从而使得客户端不加载这些实例,也不知道这些实例的存在。比方说,line5 不会被加载,但是存在于数据库。

  • 如果客户端从集合中删除了一条,比如说 line2,然后将整个组合通过 /entities/{entityName}/{entityId} API 端点进行保存,会有两种可能的输出:

  • 如果这个约束从实体被加载之后没有更改过,框架会首先在 OrderLine 集合里面恢复被过滤的 line5 实例然后只删除 line2,这个是正确的行为。

  • 但是如果这个约束在什么时候更改了,导致 line5 能被用户看见,此时,框架就不会正确的在集合内恢复这些被过滤的实例(因为从目前的约束状态看,line5 应该被客户加载过)。结果导致 line2line5 都会被删除。

如果对上面描述的场景有担忧,可以通过这种方式排除数据丢失的隐患:在表示实体的 JSON 中发送一个特殊的系统属性。这个属性被称为 __securityToken 并且会自动包含在返回的 JSON 中,如果 cuba.rest.requiresSecurityToken 设置成 true 的话。REST 客户端的责任就是在保存实体的时候将这个属性带入并返回。

实体 JSON 包含安全令牌的示例:

  1. {
  2. "id": "fa430b56-ceb2-150f-6a85-12c691908bd1",
  3. "number": "OR-000001",
  4. "items": [
  5. {
  6. "id": "82e6e6d2-be97-c81c-c58d-5e2760ae095a",
  7. "description": "Item 1"
  8. },
  9. {
  10. "id": "988a8cb5-d61a-e493-c401-f717dd9a2d66",
  11. "description": "Item 2"
  12. }
  13. ],
  14. "__securityToken": "0NXc6bQh+vZuXE4Fsk4mJX4QnhS3lOBfxzUniltchpxPfi1rZ5htEmekfV60sbEuWUykbDoY+rCxdhzORaYQNQ=="
  15. }

__securityToken 属性包含了被过滤的实例标识符的加密串,从而使得框架总是能恢复需要的信息而不管约束怎么改变。