如何在身份验证期间防止Google App Engine中的重复值/最终一致的数据存储

时间:2014-10-17 15:37:13

标签: google-app-engine jdo eventual-consistency

我们有一个使用Google App Engine作为后端的身份验证系统。底层语言和框架包括Java,JDO,Google Authentication& Google App Engine。

我们有一个用户实体。用户实体是从Google App Engine身份验证响应中保存的用户元数据(例如:名字,姓氏,电子邮件地址)。

当用户尝试注册或登录(两者都是登录事件)时,我们会扫描数据存储区以查看是否已存在具有相同电子邮件地址的用户。如果用户尚不存在,我们将创建一个新用户。如果用户确实存在,我们会更新并检索他们的用户信息,然后检索他们的应用程序数据。

我们需要运行单独的多个事务,因为“登录”页面与应用程序页面完全分开。

在某些情况下,当用户尝试在短时间内注册两次时,会创建一个重复的用户。虽然我们总是可以获取最后注册的用户,但我们确实希望查询成为唯一的JDO查询。使用唯一的JDO查询,JDO查询(在事务内部运行)有时会因找到两个相同的值(对于用户的电子邮件地址)而失败。

我们考虑了以下强制执行约束的方法:

  1. 将新注册的用户信息存储在缓存中。我们似乎没有找到任何可能暗示缓存是防止重复的合适解决方案的信息。是否可以跨机器立即使用缓存?即使它是,缓存也可能出于各种原因弹出实体。
  2. 在会话中存储用户的电子邮件。这似乎使代码膨胀,似乎是一种强制约束的奇怪方式。
  3. Google App Engine是否采用最佳做法来防止身份验证工作流程中的重复值以及单独的交易?

1 个答案:

答案 0 :(得分:4)

我建议将这两种方法结合使用:

  1. 创建一个登录实体,该实体由用户的电子邮件和主用户实体的ID组成。使用户的电子邮件成为登录实体中的密钥。这确保了它的独特性。
  2. 额外的好处是您可以将多个电子邮件地址链接到同一个用户实体。 (我们将此选项作为我们应用中的一项功能)。

    另一个额外的好处:您可以使用get()来代替您的登录查询,因为您可以通过电子邮件地址创建密钥。这样更便宜,更快,并且避免了最终的一致性问题(获得呼叫总是一致的)。

    1. 在会话中存储电子邮件地址(甚至是简单的"登录"标志)。它只需要3-5行代码来添加它并在每次登录尝试时检查它,所以我不会把它称为"膨胀"。
    2. 在我的应用程序中,我向会话添加一个标志,并在每次调用App Engine实例时检查此标志(不仅是登录调用,而是所有调用以获得额外的安全性),然后在用户注销时使会话无效。 / p>