Как сделать аутентифицированный PUT-запрос к сервису App Engine из другого источника - PullRequest
0 голосов
/ 17 марта 2019

У меня есть служба App Engine с несколькими реализованными методами, где я ограничиваю все маршруты с помощью опции login: admin в app.yaml.

Создание запроса POST для моегослужба работает:

fetch('http://localhost:8081/api/foo', {
  credentials: 'include'});

Но выполнить запрос PUT не удается

await fetch('http://localhost:8081/api/foo', {
  credentials: 'include',
  method: 'PUT',
  body: 'hi there'});

со следующей ошибкой:

Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.

Я понимаю, что это потому, что мой запрос каким-то образомне аутентифицирован, и сервер перенаправляет мой запрос на страницу входа.Чего я не понимаю, так это как его аутентифицировать.

Я использую webapp2 для обработки запросов и устанавливаю следующие заголовки:

self.response.headers['Access-Control-Allow-Credentials'] = 'true'
self.response.headers['Content-Type'] = 'application/json'
# This feels wrong, but I still don't clearly understand what this header's purpose is...
self.response.headers['Access-Control-Allow-Origin'] = self.request.headers['Origin']

Я думаю, что более глубокая проблема заключается в том, чтоЯ не понимаю, как работает эта функция входа в систему (основана ли она на файлах cookie? Почему она работает с GET, но не с PUT? ...), и я не совсем понимаю CORS.

Спасибо за любыепомощь!

Ответы [ 2 ]

1 голос
/ 17 марта 2019

Итак, после обсуждения с Дэном Корнилеску, вот решение, которое я придумала (Спасибо, Дэн!)

Вместо того, чтобы мои классы наследовали webapp2.RequestHandler, они наследуют этот пользовательский HandlerWrapper. Большая разница заключается в том, что при получении запроса «OPTIONS» (т. Е. Предварительной проверки) вход в систему не требуется. Именно это и стало причиной моей проблемы: я не смог получить предварительный запрос для проверки подлинности, поэтому теперь это не нужно.

Здесь также обрабатывается CORS со списком разрешенных источников

class HandlerWrapper(webapp2.RequestHandler):
  def __init__(self, request, response):
    super(HandlerWrapper, self).__init__(request, response)

    self.allowed_origins = [
      r'http://localhost(:\d{2,})?$', # localhost on any port
      r'https://\w+-dot-myproject.appspot.com' # all services in the app engine project
    ]
    self.allowed_methods = 'GET, PUT, POST, OPTIONS'
    self.content_type = 'application/json'
    # login mode: either 'admin', 'user', or 'public'
    self.login = 'admin'

  def dispatch(self):
    # set the Allow-Origin header.
    if self.request.headers.has_key('origin') and match_origin(self.request.headers['Origin'], self.allowed_origins):
      self.response.headers['Access-Control-Allow-Origin'] = self.request.headers['Origin']

    # set other headers
    self.response.headers['Access-Control-Allow-Methods'] = self.allowed_methods
    self.response.headers['Content-Type'] = 'application/json'
    self.response.headers['Access-Control-Allow-Credentials'] = 'true'

    # Handle preflight requests: Never require a login.
    if self.request.method == "OPTIONS":
      # For some reason, the following line raises a '405 (Method Not Allowed)'
      # error, so we just skip the dispatch and it works.
      # super(HandlerWrapper, self).dispatch()
      return

    # Handle regular requests
    user = users.get_current_user()
    if self.login == 'admin' and not users.is_current_user_admin():
      self.abort(403)
    elif self.login == 'user' and not user:
      self.abort(403)
    else:
      super(HandlerWrapper, self).dispatch()

def match_origin(origin, allowed_origins):
  for pattern in allowed_origins:
    if re.match(pattern, origin): return True
  return False
0 голосов
/ 17 марта 2019

Конфигурация login: admin основана на API пользователя , доступном только в стандартной среде 1-го поколения.Не проблема CORS.Из строки login в элементе элемента таблица:

Когда обработчик URL с параметром login отличается от необязательно сопоставляя URL, обработчик сначала проверяет, выполнил ли пользователь вход в приложение, используя опцию аутентификации .Если нет, по умолчанию пользователь перенаправляется на страницу входа.Вы также можете использовать auth_fail_action, чтобы настроить приложение так, чтобы оно просто отклоняло запросы на обработчик от пользователей, которые не прошли надлежащую аутентификацию, вместо перенаправления пользователя на страницу входа.

Чтобы использовать API пользователей, пользователь должен буквально войти в систему, прежде чем будет сделан запрос PUT.Сначала сделайте запрос GET, который перенаправит вас на страницу входа в систему, выполните вход в систему, затем выполните запрос PUT.

Если это не то, чего вы можете достичь, вам нужно использовать другой механизм аутентификации , а не тот, который основан на login: admin.

Обновление :

Вышеприведенное верно, но скорее не связано с аутентификацией API пользователяадресуется - вы упомянули, что какой-то другой метод запроса к тому же URL-адресу работает.

Полученная ошибка действительно связана с CORS, см. Ответ на предварительный запрос не проходит проверку контроля доступа .Но я бы посоветовал сосредоточиться не на принятом ответе (который касается только работы с CORS), а на , этом , то есть на правильном выполнении CORS.

...