Java 如何防止客户端更改Google云端点中的objectify@ID
我正在使用objectify将对象持久化到Google云数据存储。“主键”用@Id注释Java 如何防止客户端更改Google云端点中的objectify@ID,java,rest,google-cloud-datastore,google-cloud-endpoints,objectify,Java,Rest,Google Cloud Datastore,Google Cloud Endpoints,Objectify,我正在使用objectify将对象持久化到Google云数据存储。“主键”用@Id注释 @Entity class Car { @Id Long id; ... } 我生成客户端端点(使用Android Studio) 我需要所有字段的getter和setter,包括id,以便REST能够序列化和反序列化对象。如果我没有添加getter和setter,那么它们是由googleendpointbuilder创建的 通常,客户机从数据存储中获取实例,更改属性并将其更新回来。后端处理
@Entity
class Car {
@Id Long id;
...
}
我生成客户端端点(使用Android Studio)
我需要所有字段的getter和setter,包括id,以便REST能够序列化和反序列化对象。如果我没有添加getter和setter,那么它们是由googleendpointbuilder创建的
通常,客户机从数据存储中获取实例,更改属性并将其更新回来。后端处理新属性并将其存储在数据存储中
只要id是相同的,它就可以正常工作。但是当客户端更改id时会发生什么?因为服务器是无状态的,所以它认为另一个对象已被更新,并且插入或更新了错误的对象。换句话说,如果新id已经存在于数据存储中,则更新该记录;如果它不存在,则创建具有该id的新记录
这种行为是数据存储所固有的,但如果客户端更改id,这将使数据库混乱,因此必须有一种方法来防止这种情况
我可以看到两种解决方案:
PS:我知道上面示例中数据存储的最佳实践可能会使用VIN作为id,但这并不总是可能的。有些对象无法创建唯一标识符用作id。看起来像是许多人面临的常见问题。你可以做一件事:
上面的解决方案2是一个很好的解决方案,但是您担心在每次写入之前从
数据存储中读取数据。这可以通过使用@Cache
注释实体类来缓解,以便客户端第一次检索实体时,它们将被缓存。这样,当客户端调用后端进行更新或执行任何操作时,在比较版本时,您将不会点击数据存储。如果您担心在端点上暴露敏感属性,您有两种选择:
1) 使用@ApiResourceProperty(ignored=AnnotationBoolean.TRUE)注释它们(getter)
以便端点序列化程序跳过它们
2) 不要通过API发送您的实体,创建基本POJO,只包含您想要/需要传输的字段 为什么客户端需要更改Id?你能想出一个很好的方案来解释为什么需要更改Id吗?客户永远不应该更改Id,但我的问题是如果它确实更改了Id会发生什么。它可以更改它,因为REST是无状态的,客户端可以更改任何属性。你如何防止某人做任何恶意的事情?所以我在上一篇文章中不清楚。rest格式是简单的字符串。getter的出现/缺席并不能阻止任何人更改ID。这是一种安全错觉。服务器必须确保权限,如果有人想写入坏数据,您需要找到隔离帐户损坏的方法或进行安全检查。