安裝 flask-cors
pip install flask-cors
設置允許跨域
開啟全局允許跨域
示例
from flask_cors import CORS
CORS(app, supports_credentials=True)
CORS 的參數
參數 | 類型 | Head字段 | 說明 | 默認 |
---|---|---|---|---|
resources | 字典、迭代器或字符串 | 無 | 全局配置允許跨域的API接口 | 全部 |
origins | 列表、字符串或正則表達式 | Access-Control-Allow-Origin | 配置允許跨域訪問的源,* 表示全部允許 | * |
methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的請求方式,如:GET、POST | [GET,HEAD,POST,OPTIONS,PUT,PATCH,DELETE] |
expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定義請求響應的Head信息 | None |
allow_headers | 列表、字符串或正則表達式 | Access-Control-Request-Headers | 配置允許跨域的請求頭 | * |
supports_credentials | 布爾值 | Access-Control-Allow-Credentials | 是否允許請求發送cookie,False是不允許,True是允許 | False |
max_age | 整數、字符串 | Access-Control-Max-Age | 預檢請求的有效時長 | None |
設置單條路由允許跨域
示例
from flask_cors import *
@app.route('/')
@cross_origin(supports_credentials=True)
def hello():
name = request.args.get("name", "World")
return f'Hello, {name}!'
cross_origin 的參數
裝飾器參數 | 類型 | Head字段 | 說明 | 默認 |
---|---|---|---|---|
resources | 字典、迭代器或字符串 | 無 | 全局配置允許跨域的API接口 | 全部 |
origins | 列表、字符串或正則表達式 | Access-Control-Allow-Origin | 配置允許跨域訪問的源,* 表示全部允許 | * |
methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的請求方式,如:GET、POST | [GET,HEAD,POST,OPTIONS,PUT,PATCH,DELETE] |
expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定義請求響應的Head信息 | None |
allow_headers | 列表、字符串或正則表達式 | Access-Control-Request-Headers | 配置允許跨域的請求頭 | * |
supports_credentials | 布爾值 | Access-Control-Allow-Credentials | 是否允許請求發送cookie,False是不允許,True是允許 | False |
max_age | 整數、字符串 | Access-Control-Max-Age | 預檢請求的有效時長 | None |
注意事項
關於發送Cookie
CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials字段。
CORS(app, supports_credentials=True)
另一方面,開發者必須在AJAX請求中打開withCredentials屬性。
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
否則,即使服務器同意發送Cookie,瀏覽器也不會發送。或者,服務器要求設置Cookie,瀏覽器也不會處理。
需要注意的是,如果要發送Cookie,Access-Control-Allow-Origin就不能設為星號,必須指定明確的、與請求網頁一致的域名。
CORES(app,origins = ['example1','example2'])
同時,Cookie依然遵循同源政策,只有用服務器域名設置的Cookie才會上傳,其他域名的Cookie並不會上傳,且(跨源)原網頁代碼中的document.cookie也無法讀取服務器域名下的Cookie。
關於預檢
非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是PUT
或DELETE
,或者Content-Type
字段的類型是application/json
。
非簡單請求的CORS
請求,會在正式通信之前,增加一次HTTP
查詢請求,稱為"預檢"請求(preflight)。
瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會發出正式的XMLHttpRequest
請求,否則就報錯
"預檢"請求用的請求方法是OPTIONS
,表示這個請求是用來詢問的。頭信息里面,關鍵字段是Origin
,表示請求來自哪個源。
除了Origin字段,"預檢"請求的頭信息包括兩個特殊字段。
Access-Control-Request-Method
該字段是必須的,用來列出瀏覽器的CORS
請求會用到哪些HTTP方法,上例是PUT
。Access-Control-Request-Headers
該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段,上例是X-Custom-Header
。
服務器收到"預檢"請求以后,檢查了Origin
、Access-Control-Request-Method
和Access-Control-Request-Headers
字段以后,確認允許跨源請求,就可以做出回應。
拓展
在預檢的時候,OPTIONS
的請求不會攜帶cookie和請求的參數,正式請求才會攜帶Cookie、參數。
postman 模擬跨域請求
- 在請求頭添加
origin = 127.0.0.1
- 查看返回的請求頭信息中,是否包含允許跨域信息
Access-Control-Allow-Origin = 127.0.0.1
Access-Control-Allow-Credentials = true
Vary = Origin