Python Flask CORS - API всегда разрешает любое происхождение

Я просмотрел много SO-ответов и не могу найти эту проблему. У меня такое чувство, что я просто упускаю что-то очевидное.

У меня есть базовый API Flask, и я реализовал и расширение flask_cors, и собственный декоратор Flask [@crossdomain от Armin Ronacher]. 1 ( http://flask.pocoo.org/snippets/56/) Обе показывают одну и ту же проблему.

Это мой пример приложения:

application = Flask(__name__,
            static_url_path='',
            static_folder='static')
CORS(application)
application.config['CORS_HEADERS'] = 'Content-Type'

@application.route('/api/v1.0/example')
@cross_origin(origins=['http://example.com'])
# @crossdomain(origin='http://example.com')
def api_example():
  print(request.headers)
  response = jsonify({'key': 'value'})
  print(response.headers)
  return response

(EDIT 3 вставлено):

Когда я делаю GET-запрос к этой конечной точке от JS в браузере (от 127.0.0.1), он всегда возвращает 200, когда я ожидал увидеть:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:5000' is therefore not allowed access. The response had HTTP status code 403.

CURL:

ACCT:ENVIRON user$ curl -i http://127.0.0.1:5000/api/v1.0/example
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 20
Access-Control-Allow-Origin: http://example.com
Server: Werkzeug/0.11.4 Python/2.7.11
Date: [datetime]

{
  "key": "value"
}

ЖУРНАЛ:

Content-Length: 
User-Agent: curl/7.54.0
Host: 127.0.0.1:5000
Accept: */*
Content-Type: 


Content-Type: application/json
Content-Length: 20


127.0.0.1 - - [datetime] "GET /api/v1.0/example HTTP/1.1" 200 -

Я даже не вижу всех правильных заголовков в ответе, и, кажется, не волнует, что источник в запросе.

Есть идеи, что мне не хватает? Спасибо!


РЕДАКТИРОВАТЬ:

В качестве примечания, посмотрев пример документации здесь ( https://flask-cors.readthedocs.io/en/v1.7.4/), он показывает:

@app.route("/")
def helloWorld():
    '''
        Since the path '/' does not match the regular expression r'/api/*',
        this route does not have CORS headers set.
    '''
    return '''This view is not exposed over CORS.'''

... что довольно интересно, так как у меня уже есть корневой путь (и другие), выставленные без какого-либо украшения CORS, и они отлично работают из любого источника. Таким образом, кажется, что с этой настройкой что-то принципиально не так.

В соответствии с этим, учебник здесь ( https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask), по-видимому, указывает, что Apis Flask, естественно, должен быть выставлен без защиты (я Я бы предположил, что это только потому, что расширение CORS не было применено), но мое приложение в основном просто работает, как расширение CORS даже не существует (кроме нескольких заметок в журнале, которые вы можете увидеть).


РЕДАКТИРОВАТЬ 2:

Мои комментарии были неясными, поэтому я создал три примера конечных точек на AWS API Gateway с различными настройками CORS. Это конечные точки метода GET, которые просто возвращают "успех":

1) CORS не включен (по умолчанию):

Отклик:

XMLHttpRequest не может загрузить https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default. Ответ на запрос предварительной проверки не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок "Access-Control-Allow-Origin". Поэтому источнику " http://127.0.0.1:5000/" запрещен доступ. Ответ имел HTTP-код состояния 403.

2) CORS включен - источник ограничен:

Отклик:

XMLHttpRequest не может загрузить https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example. Ответ на запрос предварительной проверки не проходит проверку контроля доступа: заголовок "Access-Control-Allow-Origin" имеет значение " http://example.com/", которое не равно указанному источнику. Поэтому источнику " http://127.0.0.1:5000/" запрещен доступ.

3) CORS включен - подстановочный знак происхождения:

Отклик:

"success"

Я не очень разбираюсь в инфраструктуре, но я ожидал, что включение расширения Flask CORS заставит мои конечные точки API имитировать это поведение в зависимости от того, что я установил на origins= установка. Чего мне не хватает в этой настройке Flask?


РЕШЕНИЕ РЕДАКТИРОВАТЬ:

Хорошо, учитывая, что что-то с моей стороны было явно ненормальным, я сократил свое приложение и повторно реализовал некоторые очень базовые API для каждого варианта ограничения происхождения CORS. Я использовал эластичный beanstalk AWS для размещения тестовой среды, поэтому я перегрузил эти примеры и выполнил запрос JS ajax для каждого из них. Это сейчас работает.

Я получаю Access-Control-Allow-Origin ошибка на голых конечных точках. Похоже, что когда я настроил приложение для развертывания, я раскомментировал CORS(application, resources=r'/api/*')что явно позволяло все происхождение для голых конечных точек!

Я не уверен, почему мой маршрут с определенным ограничением (origins=[]) также разрешал все, но это, должно быть, была опечатка или что-то маленькое, потому что это работает сейчас.

Отдельное спасибо sideshowbarker за помощь!

1 ответ

Решение

Из вашего вопроса как есть, не совсем понятно, какое поведение вы ожидаете. Но что касается работы протокола CORS, кажется, что ваш сервер уже ведет себя как ожидалось.

В частности, curl Ответ, приведенный в вопросе, показывает этот заголовок ответа:

Access-Control-Allow-Origin: http://example.com

Это означает, что сервер, уже настроенный для оповещения браузеров, разрешает только запросы кросс-источника из внешнего кода JavaScript, выполняющегося в браузерах, если код выполняется в источнике http://example.com ,

Если ожидаемое поведение таково, что сервер теперь будет отклонять запросы от не-браузерных клиентов, таких как curl тогда конфигурация CORS сама по себе не заставит сервер это делать.

Единственное, что сервер делает по-другому, когда вы настраиваете его с поддержкой CORS, это просто отправка Access-Control-Allow-Origin заголовок ответа и другие заголовки ответа CORS. Вот и все.

Фактическое применение ограничений CORS осуществляется только браузерами, а не серверами.

Таким образом, независимо от того, какую конфигурацию CORS на стороне сервера вы выполняете, сервер все равно продолжает принимать запросы от всех клиентов и отправляет их иначе; другими словами, все клиенты из всех источников продолжают получать ответы от сервера так же, как и в противном случае.

Но браузеры будут отображать ответы от запросов из разных источников только для внешнего кода JavsScript, выполняющегося в определенном источнике, если сервер, на который был отправлен запрос, разрешает разрешение на запрос, отвечая Access-Control-Allow-Origin заголовок, который позволяет это происхождение.

Это единственное, что вы можете сделать, используя конфигурацию CORS. Вы не можете заставить сервер только принимать и отвечать на запросы от определенных источников, просто выполняя любую конфигурацию CORS на стороне сервера. Для этого вам нужно использовать что-то отличное от конфигурации CORS.

Другие вопросы по тегам