Ответ 1
Непонятно, почему/когда это когда-либо приводит к 200
; это не должно. Как упоминалось в Функция User.getUserId() в конечной точке Cloud api возвращает null для объекта пользователя, который не является нулевым, это известная проблема.
TL;DR;
В результате endpoints.get_current_user()
будет заполнен user_id
никогда. Обходной путь существует: путем хранения пользовательского объекта в хранилище данных и последующего его получения (с помощью нового get, если вы используете ndb
), значение user_id()
будет заполнено.
Вам следует настоятельно рассмотреть использование идентификатора профиля Google, связанного с учетной записью, вместо идентификатора пользователя App Engine.
История/Объяснение:
endpoints
предназначен для использования как с токенами-носителями, так и с идентификационными маркерами (для Android). Идентификаторы ID - это особый тип JWT (веб-токен JSON), подписанный в сочетании с криптографией устройства. В результате разбор пользователя из этих токенов может определять информацию, закодированную в этом токене (см. Оконечные точки оконечного устройства oauth2 для получения дополнительной информации об этом).
Поскольку эти маркеры отчеканены общим поставщиком Google Auth (OAuth 2.0) за пределами App Engine, идентификатор пользователя App Engine не известен/не используется этой службой. В результате, никогда можно заполнить user_id()
, когда для подписи запроса используется токен ID.
При использовании стандартного маркера Bearer (что будет хорошо для вашего приложения Chrome) используется AppApp метод. Это делает RPC для уровня общего уровня приложений, который предоставляет услугу, которая может получить текущего пользователя от токена. В этом случае установлен user_id()
возвращаемого пользователя WILL, однако значение пользователя не поддерживается для endpoints.get_current_user
, только адрес электронной почты и авторизация домена.
Другое обходное решение:
Вызов oauth.get_current_user()
только дорогой IF, он делает RPC. Метод _maybe_call_get_oauth_user
сохраняет значение из последнего вызова, поэтому второй раз вызов oauth.get_current_user()
не будет накладывать на сеть/скорость, кроме нескольких наносекунд, для поиска значения из Python dict
.
Это важно, потому что endpoints.get_current_user()
использует вызов oauth.get_current_user()
для определения пользователя маркера Bearer, поэтому, если вы хотите его снова вызвать, вы можете беспокоиться об этой производительности.
Если вы знаете, что никогда не будете использовать идентификационные маркеры ID или можете легко определить эти ситуации, вы можете изменить свой код, чтобы просто вызвать оба:
endpoints_user = endpoints.get_current_user()
if endpoints_user is None:
raise endpoints.UnauthorizedException(...)
oauth_user = oauth.get_current_user(known_scope)
if oauth_user is None or oauth_user.user_id() is None:
# This should never happen
raise endpoints.NotFoundException(...)
ПРИМЕЧАНИЕ. Мы все равно должны называть endpoints.get_current_user()
, потому что он всегда гарантирует, что наш токен чеканится только для одной из определенных областей, которые мы разрешили, и для одного из конкретных идентификаторов клиента мы попросили поговорить с нашим приложением.
ПРИМЕЧАНИЕ. Значение known_scope
будет зависеть от того, какая из возможных областей совпадает с маркером. Ваш список областей будет зациклирован в одном из вспомогательных методах, и если это удастся, окончательная область соответствия будет сохранена как os.getenv('OAUTH_LAST_SCOPE')
. Я бы настоятельно рекомендовал использовать это значение для known_scope
.
Лучшая альтернатива:
Как уже упоминалось, идентификатор пользователя App Engine просто не может быть подразумевается из токена ID (в текущий момент), однако идентификатор профиля Google может использоваться вместо идентификатора пользователя App Engine. (Этот идентификатор часто рассматривается как идентификатор Google+, хотя это согласуется во многих сервисах.)
Чтобы убедиться, что это значение связано с вашими токенами OR, убедитесь, что вы также запрашиваете одну из областей, не относящихся к userinfo.email
, связанных с userinfo
API:
-
https://www.googleapis.com/auth/plus.login
-
https://www.googleapis.com/auth/plus.me
-
https://www.googleapis.com/auth/userinfo.email
-
https://www.googleapis.com/auth/userinfo.profile
(Этот список областей, существующих на момент написания этой статьи 20 мая 2013 года.)
Аналогично тому, как с идентификатором пользователя App Engine в случае токена-носителя, этот идентификатор профиля Google отбрасывается endpoints.get_current_user()
, НО, он доступен для обоих видов токенов.
get_google_plus_user_id()
метод, который является частью appengine-picturesque-python
образец исправляет один из вспомогательных методов endpoints.get_current_user()
для хранения этих данных и позволяет использовать это значение, не повторяя дорогостоящие сетевые вызовы, используемые для проверки маркера носителя или идентификатора из запроса.