我看了很多SO答案,似乎无法找到这个问题。我有一种感觉,我只是错过了一些明显的东西。
我有一个基本的Flask api,我已经实现了flask_cors扩展和自定义Flask装饰器 [@crossdomain from 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
(已插入编辑3):
当我在浏览器中从JS(从127.0.0.1)向该端点发出GET请求时,它总是返回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"
}
LOG:
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 -
我甚至没有在响应中看到所有正确的标题,而且它似乎并不关心请求中的来源。
我缺少什么想法?谢谢!
编辑:
作为旁注,查看文档示例here(https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example),它显示:
@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装饰,并且它们在任何来源都可以正常工作。因此,这种设置似乎存在根本性的错误。
沿着这些方向,教程here(https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask)似乎表明Flask apis应该在没有保护的情况下自然暴露(我认为这只是因为没有应用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 enabled - Origin Restricted:
Access-Control-Allow-Headers:'Content-Type'
Access-Control-Allow-Origin:'http://example.com'
响应:
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 - Origin通配符:
响应:
"success"
我不熟悉基础架构,但我的期望是启用Flask CORS扩展会导致我的api端点模仿这种行为,具体取决于我在origins=
设置中设置的内容。我在Flask设置中缺少什么?
解决方案编辑:
好吧,所以鉴于我的结果显然不正常,我剥离了我的应用程序并为CORS原点限制的每个变体重新实现了一些非常基本的API。我一直在使用AWS的弹性beanstalk来托管测试环境,所以我重新上传这些示例并向每个示例运行JS ajax请求。它现在正在运作。
我在裸端点上遇到Access-Control-Allow-Origin
错误。看来,当我配置应用程序进行部署时,我取消注释CORS(application, resources=r'/api/*')
,这显然允许裸端点的所有来源!
我不确定为什么我的具有特定限制(origins=[]
)的路线也允许一切,但这必定是某种类型的拼写错误或小的东西,因为它现在正在运作。
特别感谢sideshowbarker提供所有帮助!
答案 0 :(得分:3)
从你的问题来看,你所期待的行为并不完全清楚。但就CORS协议的工作原理而言,似乎您的服务器已经按预期运行。
具体而言,问题中引用的curl
响应显示了此响应标题:
Access-Control-Allow-Origin: http://example.com
这表示服务器已配置为告知浏览器仅允许来自浏览器中运行的前端JavaScript代码的跨源请求(如果代码在源http://example.com
运行。
如果您期望的行为是服务器现在拒绝来自非curl
等非浏览器客户端的请求,则CORS配置本身不会导致服务器执行此操作。< / p>
当您使用CORS支持配置服务器时,服务器唯一不同的做法就是发送Access-Control-Allow-Origin
响应头和其他CORS响应头。就是这样。
CORS限制的实际执行仅由浏览器完成,而不是由服务器完成。
因此,无论您使用哪种服务器端CORS配置,服务器仍然继续接受来自所有客户端的请求,否则它将来自;换句话说,来自所有来源的所有客户端仍然继续从服务器获得响应,就像它们一样。
但 browsers 只会将来自跨源请求的响应暴露给在特定来源运行的前端JavsScript代码,如果请求被发送到opts-in的服务器通过响应{来允许请求{1}}允许该来源的标题。
这是使用CORS配置唯一可以做的事情。您不能仅通过执行任何服务器端CORS配置使服务器仅接受并响应来自特定源的请求。为此,您需要使用除CORS配置之外的其他内容。