问题描述
我试图让Flask正确处理跨站脚本。我已经从这里采取跨域装饰片段:不被Access-Control-Allow-Origin允许。
除了origin ='*'之外,我无法得到它的工作。
有人有什么想法吗? / p>
以下是完整的代码:
from datetime import timedelta
from flask import make_response,request,current_app,Flask,jsonify从functools中获取
import update_wrapper
$ b $ def crossdomain(origin = None,methods = None,headers = None,
max_age = 21600,attach_to_all = True,
automatic_options = True):
如果方法不是无:
methods =','.join(对于方法中的x进行排序(x.upper() )
如果标题不是None和不是isinstance(headers,basestring):
headers =','.join(x.upper()for x in header)
if isinstance(origin,basestring):
origin ='如果isinstance(max_age,timedelta):
max_age = max_age.total_seconds()
$ b $ def get_methods():
如果方法是不是None:
返回方法
$ b $ options_resp = current_app.make_default_options_response()
return options_resp.headers ['allow']
def decorator(f) :
def wrapped_function(* args,** kwargs):
if auto_options and request.method =='OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(* args,** kwargs))
如果不是attach_to_all和request.method!='OPTIONS':
return resp
h = resp .headers
h ['Access-Control-Allow-Origin'] =原点$ b $ ['Access-Control-Allow-Methods'] = get_methods()
h ['Access-Control-Max-Age'] = str (max_age)
如果header不是None:
h ['Access-Control-Allow-Headers'] = headers
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function,f)
返回装饰器
$ b应用程序= Flask(__ name__)
app.route('/ my_service',methods = ['POST','OPTIONS'])
@crossdomain(origin ='*',headers ='Content-Type')
def my_service():
return jsonify(foo ='跨域ftw')
if __name__ =='__main__':
app.run(host =0.0.0.0,port = 8080,debug = True)
引用我的python版本是2.7.2
Flask版本是0.7.2
我只是用pytho n版本2.7.3和Flask版本0.8。
在这些版本中, @crossdomain(origin ='myserver.com',headers ='Content-Type')
但它可以与
@crossdomain(origin ='http://myserver.com',headers =' Content-Type')
也许这对Flask 0.7.2不起作用? (尽管它在片段页面上说了什么)。
编辑:
玩完这个之后, (并升级到Flask 0.9)似乎真正的问题(或另一个问题)可能与列表中有多个允许的起源有关。换句话说,使用上面这样的代码:
@crossdomain(origin = ['http://myserver.com' ,'http://myserver2.com'],headers ='Content-Type')
doesn没有工作。
为了解决这个问题,我调整了装饰器。在此处查看代码:
如果代码位于列表中,则此代码仅返回请求站点的域。有点古怪,但至少对我来说,问题解决了:)
I'm trying to get Flask to handle cross-site scripting properly. I've taken the crossdomain decorator snippet from here:http://flask.pocoo.org/snippets/56/
In the code below, I've put the decorator snippet and the basic flask server.
I'm calling the decorator with headers='Content-Type' because otherwise I was getting "Request header field Content-Type is not allowed by Access-Control-Allow-Headers." in the browser.
So here is my question:As-is, the code below works. But when I want to restrict to only a specific server like so:
@crossdomain(origin='myserver.com', headers='Content-Type')
I get the browser error
"Origin http://myserver.com is not allowed by Access-Control-Allow-Origin."
I can't get it working for anything other than origin='*'.
Does anybody have any ideas?
Here is the complete code:
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)
For reference my python version is 2.7.2Flask version is 0.7.2
I just tried the same code with python version 2.7.3 and Flask version 0.8.
With these versions, it fails with
@crossdomain(origin='myserver.com', headers='Content-Type')
but it works with
@crossdomain(origin='http://myserver.com', headers='Content-Type')
Perhaps it just doesn't work with Flask 0.7.2? (despite what it says on the snippet page).
EDIT:After playing with this a lot more (and upgrading to Flask 0.9) it seems that the real problem (or yet another problem) might be related to having multiple allowed origins in a list. In other words, using the above code like this:
@crossdomain(origin=['http://myserver.com', 'http://myserver2.com'], headers='Content-Type')
doesn't work.
To fix this problem I tweaked the decorator. See code here:http://chopapp.com/#351l7gc3
This code returns only the domain of the requesting site if it is in the list. Kinda quirky, but at least for me, problem solved :)
这篇关于Python Flask跨站点HTTP POST - 不适用于特定的允许的来源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!