如何防止客户更改Google Cloud Endpoints中的objectify @ID [英] How to prevent client from changing objectify @ID in Google Cloud Endpoints

查看:194
本文介绍了如何防止客户更改Google Cloud Endpoints中的objectify @ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用物化将对象保存到Google Cloud数据存储区。

  @Entity 
class Car {
@Id长ID;
...
}

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

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



通常,客户端从数据存储获取实例,更改属性并更新它背部。后端处理新的属性,并将它们存储在数据存储中。



只要id相同,就可以按照假设运行。但是,当客户端更改ID时会发生什么?由于服务器是无状态的,它认为另一个对象已更新,并插入或更新错误的对象。换句话说,如果新的ID已经存在于数据存储中,那么该记录被更新;如果它不存在,那么将创建一个带有该id的新记录。



这种行为是数据存储的固有特性,但是如果客户端发生更改这个ID,所以一定有办法阻止这个。



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


  1. 正如这里所建议的 GAE - 没有Setter的Getter - 如何防止客户编写给定的属性?如何防止客户端修改对象ID? @ zgc7009,我可以让setter空着,让它不做任何事情。我试过这个,只要没有相关的对象,它就可以工作。

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


  3. 由于这两种解决方案都不太好,我相信Google的某个人一直在考虑这个问题,并且必须有更好的方法来确保跨REST的数据完整性。由于我的理解 - 而且我不知道是否可以更改 - Google Endpoints API是以不包含在URL中的方式生成的,或者在封面下发生。换句话说:通常,存储对象的id包含在URL(元数据)中。在这里,它包含在对象(有效载荷)中,因此可以由客户端进行更改。



    任何人都可以放光吗?

    PS:我知道上例中数据存储的最佳实践可能会使用VIN作为id,但这并非总是可行。有些对象中没有唯一标识符可以创建用作id。

    解决方案

    看起来像许多人遇到的常见问题。有一件事你可以做:

    上面的解决方案2是一个很好的解决方案,但您担心从数据存储在每次写入之前。这可以通过使用 @Cache 注释实体类来缓解,以便客户机第一次检索它们将被缓存的实体。这样当客户端调用后端进行更新或做比较版本时不会碰到 Datastore 的任何内容。


    I am using objectify to persist objects to Google Cloud datastore. The "primary key" is annotated with @Id.

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

    I generate the client endpoint (using Android Studio).

    I need getters and setters for all fields, including id, so that REST is able to serialize and deserialize the object. If I don't add getters and setters, then these are created by the Google endpoint builder.

    Normally, the client GETs an instance from datastore, changes attributes and UPDATEs it back. The backend processes the new attributes and stores them in datastore.

    As long as the id is the same, this works as supposed. But what happens when the client changes the id? Because the server is stateless, it believes another object has been updated and either inserts or updates the wrong object. In other words, if the new id already exists in datastore, then that record is updated; if it doesn't exist then a new record with that id is created.

    This behavior is inherent to datastore, but this will mess up the database if the client ever changes the id, so there must be a way to prevent this.

    I can see two solutions:

    1. As suggested here GAE - Getter without Setter - How to prevent client from writing a given property? How to prevent client from modifying the object ID? by @zgc7009, I could leave the setter empty and let it do nothing. I have tried this and it works, as long as there are no related objects.

    2. I could use a version field on the backend, which I increment each time UPDATE is called. This allows me to verify if client version == server version - 1 and throw an exception if not. This measure would reduce chances of updating the wrong record, but it would require a read from the datastore before each write and therefore isn't efficient.

    As both solutions are not nice, I believe somebody at Google has been thinking about this and there must be a better way to ensure data integrity across REST. Due to my understanding - and I don't know if that can be changed -, Google Endpoints API is generated in a way where the id is not included within the URL, or this happens under the cover. In other words: Normally the id under which an object is stored is included with the URL (metadata). Here, it is included with the object (payload) and can therefore be changed by the client.

    Can anybody shed light please?

    PS: I know that best practices for datastore in above example would probably using the VIN as id, but this is not always possible. There are objects where no unique identifier can be created for use as id.

    解决方案

    Looks like a common problem many have faced. There is one thing you can do:

    Your solution 2 above is a good one but you're worried about reading from the Datastore before each write. This can be mitigated by annotating your entity class with @Cache so that the first time a client retrieves entities they will be cached. This way when the client calls your backend to update or do whatever you will not hit the Datastore when comparing the versions.

    这篇关于如何防止客户更改Google Cloud Endpoints中的objectify @ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆