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