Flask 跨域问题
一、什么是跨域
跨域是指:瀏覽器A從服務(wù)器B獲取的靜態(tài)資源,包括Html、Css、Js,然后在Js中通過Ajax訪問C服務(wù)器的靜態(tài)資源或請求。即:瀏覽器A從B服務(wù)器拿的資源,資源中想訪問服務(wù)器C的資源。
同源策略是指:瀏覽器A從服務(wù)器B獲取的靜態(tài)資源,包括Html、Css、Js,為了用戶安全,瀏覽器加了限制,其中的Js通過Ajax只能訪問B服務(wù)器的靜態(tài)資源或請求。即:瀏覽器A從哪拿的資源,那資源中就只能訪問哪。
同源是指:同一個請求協(xié)議(如:Http或Https)、同一個Ip、同一個端口,3個全部相同,即為同源。
跨域的處理
W3C組織制定了一個Cross-Origin Resource Sharing規(guī)范,簡寫為Cors,現(xiàn)在這個規(guī)范已經(jīng)被大多數(shù)瀏覽器支持,Cors 專門用來處理跨域的需求。
Cors需要在后端應(yīng)用進行配置,因此,是一種跨域的后端處理方式,這么做也容易理解,一個你不認(rèn)識的源來訪問你的應(yīng)用,自然需要應(yīng)用進行授權(quán)。除了后端處理方式,也有前端的解決方案,如:JSONP,這里我們主要講解Flask后端配置方案.
跨域的分類
跨域分為以下3種
| 簡單請求 | Simple Request | 發(fā)起的Http請求符合: 1.無自定義請求頭,只有Accept、Accept-Language、Content-Language、Last-Event-ID 2.請求動詞為GET、HEAD或POST之一 3.動詞為POST時,Content-Type是application/x-www-form-urlencoded,multipart/form-data或text/plain之一 |
| 復(fù)雜請求 | Preflighted Request | 發(fā)起的Http請求符合其中之一: 1.包含了自定義請求頭 2.請求動詞不是GET、HEAD或POST 3.動詞是POST時, Content-Type不是application/x-www-form-urlencoded,multipart/form-data或text/plain。 即:簡單請求的相反 |
| 憑證請求 | Requests with Credential | 發(fā)起的Http請求中帶有憑證 |
簡單請求
簡單請求的發(fā)送從代碼上來看和普通的XHR沒太大區(qū)別,但是HTTP頭當(dāng)中要求總是包含一個域(Origin)的信息。該域包含協(xié)議名、地址以及一個可選的端口。不過這一項實際上由瀏覽器代為發(fā)送,并不是開發(fā)者代碼可以觸及到的。
簡單請求的部分響應(yīng)頭如下:
如果僅僅是簡單請求,那么即便不用CORS也沒有什么大不了,但CORS的復(fù)雜請求就令CORS顯得更加有用了。簡單來說,任何不滿足上述簡單請求要求的請求,都屬于復(fù)雜請求。比如說你需要發(fā)送PUT、DELETE等HTTP動作,或者發(fā)送Content-Type: application/json的內(nèi)容。
復(fù)雜請求
復(fù)雜請求先發(fā)送一種"預(yù)請求",此時作為服務(wù)端,也需要返回"預(yù)回應(yīng)"作為響應(yīng)。預(yù)請求實際上是對服務(wù)端的一種權(quán)限請求,只有當(dāng)預(yù)請求成功返回,實際請求才開始執(zhí)行。預(yù)請求以O(shè)PTIONS形式發(fā)送,當(dāng)中同樣包含域,并且還包含了兩項CORS特有的內(nèi)容:
顯而易見,這個預(yù)請求實際上就是在為之后的實際請求發(fā)送一個權(quán)限請求,在預(yù)回應(yīng)返回的內(nèi)容當(dāng)中,服務(wù)端應(yīng)當(dāng)對這兩項進行回復(fù),以讓瀏覽器確定請求是否能夠成功完成。復(fù)雜請求的部分響應(yīng)頭及解釋如下:
一旦預(yù)回應(yīng)如期而至,所請求的權(quán)限也都已滿足,則實際請求開始發(fā)送。
目前大部分Modern瀏覽器已經(jīng)支持完整的CORS,但IE直到IE11才完美支持,所以對于PC網(wǎng)站,還是建議采用其他解決方案,如果僅僅是移動端網(wǎng)站,大可放心使用。
Flask配置跨域
flask 配置cors 有兩種方式,一種使用自帶的cors,一種自定義返回頭
第一種,自定義返回頭
@app.after_request def af_request(resp): """#請求鉤子,在所有的請求發(fā)生后執(zhí)行,加入headers。:param resp::return:"""resp = make_response(resp)resp.headers['Access-Control-Allow-Origin'] = '*'resp.headers['Access-Control-Allow-Methods'] = 'GET,POST'resp.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type'return resp第二種,使用cors
Flask配Cors跨域,使用Flask-CORS包,詳細(xì)文檔,參見:?https://flask-cors.readthedocs.io/en/latest/
flask-cors 也提供了兩種方式:
| @cross_origin裝飾器 | 配置單個路由 | 適用于配置特定的API接口 |
| CORS函數(shù) | 配置全局API接口 | 適用于全局的API接口配置 |
安裝flask-cors
pip install flask-cors第一種:使用@cross_origin裝飾器
@app.route("/") @cross_origin() def helloWorld():return "Hello, cross-origin-world!"CORS參數(shù)說明?
| origins | 列表、字符串或正則表達(dá)式 | Access-Control-Allow-Origin | 配置允許跨域訪問的源,*表示全部允許 |
| methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的請求方式,如:GET、POST |
| expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定義請求響應(yīng)的Head信息 |
| allow_headers | 列表、字符串或正則表達(dá)式 | Access-Control-Request-Headers | 配置允許跨域的請求頭 |
| supports_credentials | 布爾值 | Access-Control-Allow-Credentials | 是否允許請求發(fā)送cookie,false是不允許 |
| max_age | 整數(shù)、字符串 | Access-Control-Max-Age | 預(yù)檢請求的有效時長 |
第二種:使用CORS函數(shù)
#################### 應(yīng)用全局配置 #################### from flask_cors import *app = Flask(__name__) CORS(app, supports_credentials=True, resources=r"/*")@app.route("/api/v1/users") def list_users():return "user example"#################### 單獨Blueprints配置 #################### api_v1 = Blueprint('API_v1', __name__) CORS(api_v1) @api_v1.route("/api/v1/users/") def list_users():return "user example"CORS參數(shù)說明
| resources | 字典、迭代器或字符串 | 無 | 全局配置允許跨域的API接口 |
| origins | 列表、字符串或正則表達(dá)式 | Access-Control-Allow-Origin | 配置允許跨域訪問的源,*表示全部允許 |
| methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的請求方式,如:GET、POST |
| expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定義請求響應(yīng)的Head信息 |
| allow_headers | 列表、字符串或正則表達(dá)式 | Access-Control-Request-Headers | 配置允許跨域的請求頭 |
| supports_credentials | 布爾值 | Access-Control-Allow-Credentials | 是否允許請求發(fā)送cookie,false是不允許 |
| max_age | 整數(shù)、字符串 | Access-Control-Max-Age | 預(yù)檢請求的有效時長 |
注意:繼承Resource類來寫的RESTful-API接口
繼承Resource類來寫的RESTful-API接口不能使用上述辦法。解決辦法是在需要支持跨域請求的API類下,添加一個類方法options,就可以解決跨域問題
原因是跨域問題請求的時候,無論是POST請求還是PUT請求,前端都會優(yōu)先發(fā)起一個OPTIONS請求確認(rèn)請求允許范圍.那么在解決跨域請求時,只需要在每個資源url中加入options請求方式,并返回適當(dāng)?shù)捻憫?yīng)頭信息就能解決跨域問題.
class YourAPI(Resource):def options(self):return {'Allow': '*'}, 200, {'Access-Control-Allow-Origin': '*','Access-Control-Allow-Methods': 'HEAD, OPTIONS, GET, POST, DELETE, PUT','Access-Control-Allow-Headers': 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild',}具體可配置參數(shù)解釋:
-
Access-Control-Allow-Origin
這個頭部信息由服務(wù)器返回,用來明確指定那些客戶端的域名允許訪問這個資源。它的值可以是:-使用" * " —— 允許任意域名
- 一個完整的域名名字(比如:https://example.com)
如果你需要客戶端傳遞驗證信息到頭部(比如:cookies)。這個值不能為 * —— 必須為完整的域名(這點很重要)。
-
Access-Control-Allow-Credentials
這個頭部信息只會在服務(wù)器支持通過cookies傳遞驗證信息的返回數(shù)據(jù)里。它的值只有一個就是 true??缯军c帶驗證信息時,服務(wù)器必須要爭取設(shè)置這個值,服務(wù)器才能獲取到用戶的cookie。 -
Access-Control-Allow-Headers
提供一個逗號分隔的列表表示服務(wù)器支持的請求數(shù)據(jù)類型。假如你使用自定義頭部(比如:x-authentication-token 服務(wù)器需要在返回OPTIONS請求時,要把這個值放到這個頭部里,否則請求會被阻止)。 -
Access-Control-Expose-Headers
相似的,這個返回信息里包含了一組頭部信息,這些信息表示那些客戶端可以使用。其他沒有在里面的頭部信息將會被限制(譯者注:這個頭信息實戰(zhàn)中使用較少)。 -
Access-Control-Allow-Methods
一個逗號分隔的列表,表明服務(wù)器支持的請求類型(比如:GET, POST) -
Origin
這個頭部信息,屬于請求數(shù)據(jù)的一部分。這個值表明這個請求是從瀏覽器打開的哪個域名下發(fā)出的。出于安全原因,瀏覽器不允許你修改這個值。
總結(jié)
以上是生活随笔為你收集整理的Flask 跨域问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机uc怎么放大页面_手机网站怎样做可以
- 下一篇: 算法基础之搜索和经典排序