繁体   English   中英

如何防止客户端更改Google Cloud Endpoints中的objectify @ID

[英]How to prevent client from changing objectify @ID in Google Cloud Endpoints

我正在使用objectify将对象持久保存到Google Cloud数据存储中。 “主键”用@Id注释。

@Entity
class Car {
    @Id Long id;
    ...
}

我生成客户端端点(使用Android Studio)。

我需要所有字段(包括id)的获取器和设置器,以便REST能够序列化和反序列化对象。 如果我不添加getter和setter,则它们是由Google端点构建器创建的。

通常,客户端从数据存储区获取实例,更改属性并将其更新回来。 后端处理新属性并将其存储在数据存储区中。

只要id相同,就可以按预期工作。 但是,当客户端更改ID时会发生什么? 由于服务器是无状态的,因此它认为另一个对象已被更新,并且可以插入或更新错误的对象。 换句话说,如果新ID已存在于数据存储区中,则将更新该记录;否则,将更新该记录。 如果不存在,则创建具有该ID的新记录。

此行为是数据存储所固有的,但是如果客户端更改了ID,这将使数据库混乱,因此必须有一种方法来防止这种情况。

我可以看到两种解决方案:

  1. 如此处所建议, GAE-不使用Setter的Getter-如何防止客户端编写给定属性? 如何防止客户端修改对象ID? 通过@ zgc7009,我可以将设置器保留为空,而不执行任何操作。 只要没有相关的对象,我都尝试过并且可以使用。

  2. 我可以在后端使用版本字段,每次调用UPDATE时,该字段就会增加。 这使我可以验证客户端版本是否==服务器版本-1,否则抛出异常。 此措施将减少更新错误记录的机会,但在每次写入之前都需要从数据存储中进行读取,因此效率不高。

由于这两种解决方案都不理想,我相信Google有人正在考虑这一点,因此必须有一种更好的方法来确保跨REST的数据完整性。 根据我的理解-而且我不知道是否可以更改-,Google Endpoints API的生成方式是在URL中未包含ID,或者这种情况是在后台进行的。 换句话说:通常,URL(元数据)中包含用于存储对象的ID。 在此,它包含在对象(有效负载)中,因此可以由客户端更改。

有人可以照亮吗?

PS:我知道上面示例中的数据存储最佳做法可能是使用VIN作为ID,但这并不总是可能的。 在某些对象中,无法创建唯一标识符用作ID。

看起来是许多人面临的常见问题。 您可以做一件事:

上面的解决方案2是很好的解决方案,但您担心每次写入之前都要从Datastore读取Datastore 这可以通过使用@Cache注释您的实体类来减轻,以便客户端第一次检索实体时将对其进行缓存。 这样,当客户端调用您的后端进行更新或执行比较版本时不会执行Datastore时。

如果您担心在端点上公开敏感属性,则有两种选择:

1)用@ApiResourceProperty(ignored=AnnotationBoolean.TRUE) )注释它们( @ApiResourceProperty(ignored=AnnotationBoolean.TRUE)以便端点序列化程序跳过它们。

2)不要通过API发送您的实体,仅使用您要/需要转移的字段创建基本的POJO。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM