Python Flask CORS - API始终允许任何来源

时间:2017-08-07 00:54:33

标签: python flask cors flask-cors

我看了很多SO答案,似乎无法找到这个问题。我有一种感觉,我只是错过了一些明显的东西。

我有一个基本的Flask api,我已经实现了flask_cors扩展和自定义Flask装饰器 [@crossdomain from Armin Ronacher]1http://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 -

我甚至没有在响应中看到所有正确的标题,而且它似乎并不关心请求中的来源。

我缺少什么想法?谢谢!

编辑:

作为旁注,查看文档示例herehttps://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装饰,并且它们在任何来源都可以正常工作。因此,这种设置似乎存在根本性的错误。

沿着这些方向,教程herehttps://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:

响应:

  

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提供所有帮助!

1 个答案:

答案 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配置之外的其他内容。