2017-08-07 60 views
2

我已經瀏覽了許多SO答案,似乎無法找到此問題。我有一種感覺,我只是想念一些明顯的東西。Python Flask CORS - API始終允許任何來源

我有一個基本的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插入):

當我做一個GET請求,以便從JS端點在瀏覽器中(從127.0.0.1),它總是返回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. 

捲曲:

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)似乎表明,瓶API應該自然無保護地暴露(我假設只是因爲CORS擴展尚未應用),但我的應用程序基本上只是工作就像CORS擴展甚至不存在(除了日誌中的幾個註釋,你可以看到)。


編輯2:

我的意見是不清楚的,所以我創建了三個例子端點上AWS API網關與不同CORS設置。他們是GET方法端點簡單地返回 「成功」:

1)CORS未啓用(默認):

響應:

的XMLHttpRequest不能加載 https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default。 對預檢請求的響應未通過訪問控制檢查:否 請求的 資源上存在「訪問控制 - 允許來源」標頭。 'http://127.0.0.1:5000'因此不允許 訪問。響應有HTTP狀態代碼403

2)CORS啓用 - 產地限制:

響應:

的XMLHttpRequest不能加載 https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example。 對預檢請求的響應未通過訪問控制檢查: '訪問控制允許來源'標頭的值'http://example.com' 不等於提供的原點。因此不允許訪問原產地 'http://127.0.0.1:5000'。

3)CORS啓用 - 產地通配符:

響應:

"success" 

我對基礎設施沒有經驗,但我的期望是啓用Flask CORS擴展會導致我的api端點模仿這種行爲,這取決於我在origins=設置中設置的內容。我在這個Flask設置中缺少什麼?


解決方案編輯:

好了,因爲在我結束一些明顯不正常,我剝了下來我的應用程序,並重新實現一些非常基本的API CORS產地限制的每個變化。我一直使用AWS的彈性beanstalk來託管測試環境,所以我重新上傳了這些示例,並向每個請求發送了一個JS ajax請求。它正在工作。

我在裸露的終端上遇到了Access-Control-Allow-Origin錯誤。看起來,當我配置應用程序進行部署時,我取消了註釋CORS(application, resources=r'/api/*'),這明顯允許所有裸體終端的源代碼!

我不知道爲什麼我的路線有特定的限制(origins=[])也允許一切,但這肯定是某種類型的打字錯誤或小事,因爲它現在正在工作。

特別感謝sideshowbarker的所有幫助!

+0

對不起,我還不清楚你的期望。編輯2中的所有情況在我看來都像預期的那樣工作。案例#1是你會考慮按預期工作的,對吧?在那一箇中​​,你沒有爲該端點啓用CORS,所以瀏覽器不允許訪問該響應。就CORS協議而言,第二種情況也是按照預期的方式工作,因爲您已將允許的來源設置爲「http:// example.com」,但您從「http://127.0.0.1」發送請求:5000',所以瀏覽器不會讓你的代碼在'http://127.0.0。1:5000'參見響應 – sideshowbarker

+0

就CORS協議而言,情況#3也按預期工作 - 因爲根據您所說的配置,「允許任何來源運行的前端代碼訪問來自該端點的響應」,所以在您發送請求的源中運行的代碼成功訪問響應。 – sideshowbarker

+0

我不明白是什麼*「導致我的API端點模仿這種行爲,這取決於我在'origins ='設置中設置的內容」*意味着 – sideshowbarker

回答

3

從現在的問題來看,並不完全清楚你期望的行爲。但就CORS協議的工作原理而言,您的服務器似乎已經按預期工作。

具體而言,在問題引curl響應顯示了這個響應頭:

Access-Control-Allow-Origin: http://example.com 

這表明已經配置告訴瀏覽器服務器,僅允許從前端的JavaScript在瀏覽器中,如果運行的代碼跨域請求代碼在原點http://example.com處運行。

如果您期望的行爲是服務器現在拒絕來自非瀏覽器客戶端(如curl)的請求,那麼CORS配置本身不會導致服務器執行此操作。

當您使用CORS支持配置服務器時,服務器做的唯一不同之處就是發送Access-Control-Allow-Origin響應標頭和其他CORS響應標頭。而已。

CORS限制的實際執行只能由瀏覽器完成,而不能由服務器完成。因此,無論服務器端的CORS配置如何,服務器都會繼續接受來自所有客戶端的請求,並且不會接受來自其他客戶端的請求;換句話說,來自所有來源的所有客戶仍然繼續從服務器獲得響應,就像他們會這樣。

但是瀏覽器只會暴露從跨源的請求的響應,以前端JavsScript代碼在特定原點運行如果服務器請求通過用Access-Control-Allow-Origin頭部,它允許其響應發送到選擇採用-到允許請求起源。

這是您可以使用CORS配置完成的唯一一件事。你不能讓一臺服務器只接受和響應來自特定來源的請求,只要做任何服務器端CORS配置。要做到這一點,您需要使用除CORS配置以外的其他功能。

+0

感謝您對此的幫助。也許我可以用一個例子來解釋。我在AWS上設置了一個API網關端點,並嘗試在不啓用CORS的情況下訪問它。它返回這個響應:「No'Access-Control-Allow-Origin'標題出現在請求的資源上,Origin'http://another-example.com'因此不被允許訪問。」我基本上試圖讓我的Flask應用程序在應用程序中未啓用CORS時發送該響應,但它始終允許任何訪問,即使來自瀏覽器中js的ajax請求也是如此。我以爲我瞭解CORS,但是可能缺少一個服務器設置? – Feedslant

+0

簡單來說,似乎我的應用程序根本沒有同源策略。我對基礎設施不太瞭解,但我認爲這是默認啓用的。到目前爲止,谷歌搜索在幫助實施這項政策方面沒有多大幫助。 – Feedslant

+0

我上面的評論是誤導/不清楚的,所以我在我的問題中的「編輯2」下添加了其他信息。再次感謝你的幫助。 – Feedslant

相關問題