Python Flask cross site HTTP POST - не работает для определенных разрешенных источников

Я пытаюсь заставить Flask правильно обрабатывать межсайтовые скрипты. Я взял фрагмент декоратора crossdomain отсюда: http://flask.pocoo.org/snippets/56/

в приведенном ниже коде я поместил фрагмент декоратора и базовый сервер колб.

Я звоню декоратору с headers= 'Content-Type' потому что в противном случае я получал "поле заголовка запроса Content-Type не разрешено Access-Control-Allow-Headers."в браузер.

Так вот мой вопрос: Как есть, код ниже работает. Но когда я хочу ограничить только определенный сервер, например:

@crossdomain(origin='myserver.com', headers='Content-Type')

Я получаю ошибку браузера

" происхождение http://myserver.com не допускается с помощью Access-Control-Allow-Origin."

Я не могу заставить его работать ни для чего, кроме origin='*'.

есть ли у кого-нибудь идеи?

здесь код:

from datetime import timedelta
from flask import make_response, request, current_app, Flask, jsonify
from functools import update_wrapper

def crossdomain(origin=None, methods=None, headers=None,
            max_age=21600, attach_to_all=True,
            automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, basestring):
        origin = ', '.join(origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        if methods is not None:
            return methods

        options_resp = current_app.make_default_options_response()
        return options_resp.headers['allow']

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            if automatic_options and request.method == 'OPTIONS':
            resp = current_app.make_default_options_response()
            else:
                resp = make_response(f(*args, **kwargs))
            if not attach_to_all and request.method != 'OPTIONS':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = str(max_age)
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return update_wrapper(wrapped_function, f)
    return decorator

app = Flask(__name__)

@app.route('/my_service', methods=['POST', 'OPTIONS'])
@crossdomain(origin='*', headers='Content-Type')
def my_service():
    return jsonify(foo='cross domain ftw')

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8080, debug=True)

для справки моя версия python-2.7.2 Фляга версия 0.7.2

2 ответов


Я только что попробовал тот же код с python версии 2.7.3 и колбу версии 0.8.

С этими версиями, он выдает

@crossdomain(origin='myserver.com', headers='Content-Type')

но он работает с

@crossdomain(origin='http://myserver.com', headers='Content-Type')

возможно, это просто не работает с флягой 0.7.2? (несмотря на то, что говорится на странице фрагмента).


изменить: После игры с этим намного больше (и обновления до Flask 0.9) кажется, что реальная проблема (или еще одна проблема) может быть связана с наличием нескольких разрешенных происхождение в списке. Другими словами, используя приведенный выше код следующим образом:

@crossdomain(origin=['http://myserver.com', 'http://myserver2.com'], headers='Content-Type')

не работает.

чтобы исправить эту проблему, я настроил декоратора. См. код здесь: http://chopapp.com/#351l7gc3

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


Python изо всех сил пытается помешать вам подвергать себя атакам межсайтовых сценариев.

одно исправление-это сдаться, и ваши запросы попадают на тот же сервер, на котором работает сценарий flask. Получение JSON с удаленных серверов, определенных в строках, в любом случае рискованно.

я смог исправить это, позволяя браузеру держать себя на том же сервере, как это:

$('a#calculate').bind('click', function() {
  $.getJSON('/_add_numbers', { 
    a: $('input[name="a"]').val(),
    b: $('input[name="b"]').val()
  }, function(data) {
    $("#result").text(data.request);
  });
  return false;
});

обратите внимание, как getJSON метод передается /_add_numbers. Что связывается с браузером, чтобы остаться на том же хосте и искать эту страницу. Тогда браузер счастлив и безопасен, мы остаемся на одном хосте, и вы никогда не получите ошибку:

Origin http://myserver.com is not allowed by Access-Control-Allow-Origin