4.8. 集合属性的安全约束

考虑下面这个情况:

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

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

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

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

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

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

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

实体 JSON 包含 security token 的示例:

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

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