【问题标题】:Retrieving the Google User Object's ID Value检索 Google 用户对象的 ID 值
【发布时间】:2025-12-30 09:15:18
【问题描述】:

我一直很困惑。我一直在使用 Google 的 User 对象,可以在这里找到:

https://cloud.google.com/appengine/docs/python/refdocs/google.appengine.api.users#google.appengine.api.users.User

在阅读了一些资源后,有人告诉我存储 User 对象本身并不是一个好主意,因为电子邮件可能会发生变化。 Google 建议您应该存储 User_Id 本身,因为这样做是永久安全的(即,它始终保持静态)。

当我获取当前用户并尝试使用用户对象上的user_id() 方法获取 User_Id 值时,我得到了None 值响应。

current_user = endpoints.get_current_user()
print current_user.user_id()
>> None

但是,如果我将 current_user 保存为 NDB 中的 UserProperty,然后检索相同的值,我会得到 user_id。例如:

google_user = ndb.UserProperty(required = True)

print google_user.user_id()
>> 12345678901234567890

谷歌用户对象应该如何处理?更重要的是,为什么在 NDB 保存值之前 user_id 的值为 None ?这是一种帐户/电子邮件验证吗?

您可以在此处找到来自 Google 的建议:

https://cloud.google.com/appengine/docs/python/users/userobjects

“我们强烈建议您不要存储 UserProperty,因为它包含电子邮件地址以及用户的唯一 ID。如果用户更改了他们的电子邮件地址,并且您将其旧的、存储的用户与新的用户值进行比较,他们将不匹配。相反,请考虑使用 User 用户 ID 值作为用户的稳定唯一标识符。"

编辑:我应该提一下,我正在localhost 上进行测试。部署应用程序时,endpoints.get_current_user() 的处理方式是否不同?

这是 Google 使用的示例:

class ModelWithUser(ndb.Model):
    user_id = ndb.StringProperty()
    color = ndb.StringProperty()

    @classmethod
    def get_by_user(cls, user):
        return cls.query().filter(cls.user_id == user.user_id()).get()

如果我通过当前经过身份验证的用户(我无权访问)的 user_id 查询 ModelWithUser,我应该如何从 ModelWithUser 获取用户?呸。

【问题讨论】:

    标签: python google-cloud-platform google-cloud-endpoints


    【解决方案1】:

    好的,在通过 Google 搜索进行挖掘后,我遇到了这个关于如何在不访问数据存储区的情况下获取当前用户 ID 的帖子:

    https://code.google.com/p/googleappengine/issues/detail?id=8848

    Google 的官方回应是这是已知问题,不会修复:

    “解决此问题不在我们的路线图中 - Google ID 令牌包含 G+ 用户 ID,而不是 App Engine 用户 ID,因此提供的 App Engine 用户对象不能包含 App Engine 用户 ID。我们建议您使用其中一种上面提到的解决方法。”

    解决方法在这里(来自 Google 开发人员):https://code.google.com/p/googleappengine/issues/detail?id=8848#c39

    def _getUserId():
        """A workaround implementation for getting userid."""
        auth = os.getenv('HTTP_AUTHORIZATION')
        bearer, token = auth.split()
        token_type = 'id_token'
        if 'OAUTH_USER_ID' in os.environ:
            token_type = 'access_token'
        url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?%s=%s'
               % (token_type, token))
        user = {}
        wait = 1
        for i in range(3):
            resp = urlfetch.fetch(url)
            if resp.status_code == 200:
                user = json.loads(resp.content)
                break
            elif resp.status_code == 400 and 'invalid_token' in resp.content:
                url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?%s=%s'
                       % ('access_token', token))
            else:
                time.sleep(wait)
                wait = wait + i
        return user.get('user_id', '')
    

    尽管我很喜欢在 Google 的堆栈中工作,但我承认 - 这很奇怪。

    编辑:

    可以在此处找到另一种解决方法:

    How can I determine a user_id based on an email address in App Engine?

    【讨论】:

      【解决方案2】:

      这个question 是相关的(UserProperty 类的存在只是为了向后兼容现有的数据存储模式)。

      而且,正如您问题中引用的文档中所说:

      user_id()

      获取用户的用户ID。

      返回

      永久唯一标识字符串或无。如果电子邮件 地址已明确设置,这将返回 None。

      是否明确设置了用户的电子邮件地址?

      【讨论】:

      • 我也看到了。但是,如果您不存储对象,我遇到的问题是如何检索 user_id? current_user().user_id() 返回None
      • @Kris,endpoints 代表什么?它应该是 google appengine api 的 users 类,from google.appengine.api import users
      • @sclicard 嘿,抱歉回复晚了。它来自这里cloud.google.com/appengine/docs/python/endpoints/…。我猜它是同一个确切的类。