摘要:說明測試使用的接口域名,多域名為和。設置多域名嘗試直接通過的模塊追加值實現,如下接口請求和響應頭如下當前域為,需跨域請求的資源。故通過該方法不能設置多域名進行。
首發于 樊浩柏科學院
平常我們遇到跨域問題時,常使用 cors(Cross-origin resource sharin)方式解決。不知你是否注意到,在設置響應頭 Access-Control-Allow-Origin 域的值時,只允許設置一個域名,這意味著不能同時設置多個域名來共享資源。而在 Yii2 中直接使用"Origin" => ["http://www.site1.com", "http://www.site2.com"]的形式卻可以設置多個 cors 域名值,Why?
其實,Yii2 中采用了動態設置 Access-Control-Allow-Origin 域值的方法來解決這個問題。
說明:測試使用的接口域名api.d.fanhaobai.com,cros 多域名為www.d.yii.com和www.fq.yii.com。Nginx設置多域名
嘗試直接通過 Nginx 的add_header模塊追加 Access-Control-Allow-Origin 值實現,如下:
add_header Access-Control-Allow-Origin http://www.fq.yii.com; add_header Access-Control-Allow-Origin http://www.d.yii.com;
接口 請求 和 響應頭 如下:
Response Headers Access-Control-Allow-Origin: http://www.fq.yii.com Access-Control-Allow-Origin: http://www.d.yii.com Connection: keep-alive Content-Type: application/json; charset=UTF-8 ... ... Request Headers Accept: */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8 Host: api.d.fanhaobai.com Origin: http://www.fq.yii.com Proxy-Connection: keep-alive ... ...
當前域為www.fq.yii.com,需跨域請求http://api.d.fanhaobai.com/v1/config/list.json的資源。瀏覽器拋出如下跨域錯誤:
XMLHttpRequest cannot load http://api.d.fanhaobai.com/v1/config/list.json. The "Access-Control-Allow-Origin" header contains multiple values "http://www.fq.yii.com, http://www.d.yii.com", but only one is allowed. Origin "http://www.fq.yii.com" is therefore not allowed access.
以上信息明確說明,Access-Control-Allow-Origin 只能設置為一個值,即每次請求只能對應一個域名值。故通過該方法不能設置多域名進行 cors。
Yii2設置多域名Yii2 設置多域名 cors,只需在對應控制器(ConfigController)中設置 cors 行為,如下:
class BaseController extends Controller { /** * @inheritdoc */ public function behaviors() { return [ "corsFilter" => [ "class" => yiifiltersCors::className(), "cors" => [ //運行cors域名列表 "Origin" => ["http://www.d.yii.com", "http://www.fq.yii.com"], "Access-Control-Allow-Credentials" => true, ] ], ]; } }
重新在www.fq.yii.com發送 cors 請求,發現此時已經不存在跨域問題。響應頭 如下:
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://www.fq.yii.com Connection: keep-alive Content-Type: application/json; charset=UTF-8 ... ...
我們會發現,Access-Control-Allow-Origin 域的值為http://www.fq.yii.com,剛好為當前域名一致,且只有一個值,并未出現設置的http://www.d.yii.com值。
同時,在www.d.yii.com下發送 cors 請求,也不存在跨域問題。響應頭中 Access-Control-Allow-Origin 值為http://www.d.yii.com。
由此可知,Yii2 在控制器行為中設置 Origin 項,只是一個域名白名單,而返回的 Access-Control-Allow-Origin 同請求的域名一致且在這個白名單中,這個 Access-Control-Allow-Origin 由 Yii2 根據當前請求所在域名進行了動態處理。
Yii2動態Access-Control-Allow-Origin查看 Yii2 的yiifiltersCors類源碼,如下:
class Cors extends ActionFilter { /** * @var array CORS所用的響應頭 */ public $cors = [ "Origin" => ["*"], "Access-Control-Request-Method" => ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"], "Access-Control-Request-Headers" => ["*"], "Access-Control-Allow-Credentials" => null, "Access-Control-Max-Age" => 86400, "Access-Control-Expose-Headers" => [], ]; /** * 執行action前要做的事 * @inheritdoc */ public function beforeAction($action) { $this->request = $this->request ?: Yii::$app->getRequest(); $this->response = $this->response ?: Yii::$app->getResponse(); ... ... $requestCorsHeaders = $this->extractHeaders(); //獲取cors所用的響應頭 $responseCorsHeaders = $this->prepareHeaders($requestCorsHeaders); //設置cors所用的響應頭 $this->addCorsHeaders($this->response, $responseCorsHeaders); return true; } /** * 處理cors所用的響應頭,動態處理Access-Control-Allow-Origin域 * @param array $requestHeaders CORS headers we have detected * @return array CORS headers ready to be sent */ public function prepareHeaders($requestHeaders) { $responseHeaders = []; //$requestHeaders["Origin"]為源地址,請求所在域名 if (isset($requestHeaders["Origin"], $this->cors["Origin"])) { //源地址在白名單中,則設置Access-Control-Allow-Origin為源地址 if (in_array("*", $this->cors["Origin"]) || in_array($requestHeaders["Origin"], $this->cors["Origin"])) { $responseHeaders["Access-Control-Allow-Origin"] = $requestHeaders["Origin"]; } } ... ... } }
主要思想就是,查看源地址是否在 cors 白名單中,在則設置 Access-Control-Allow-Origin 域的值為源地址。這樣就能滿足 Access-Control-Allow-Origin 為一個值的限制,同時也能允許指定的域名進行 cors。
注意:使用該方法請確保 Nginx 配置中未操作 Access-Control-Allow-Origin 域。總結
通過 Nginx 設置 Access-Control-Allow-Origin 進行 cors,有且只能有一個特定域名,局限性較大。通過代碼邏輯操作 Access-Control-Allow-Origin 來實現 cors,則比較靈活,能解決多個域名進行 cors 的需求,但是如果接口異常,跨域設置則會失效。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29763.html
摘要:可是,我們的域名有這三個域名僅僅是不同的環境,因此,的跨域名訪問就引出來了。無論是一二級域名,和不同域名下的跨域,無非要達到兩點客戶端訪問同一個所有域名對應的服務器訪問的的數據的位置必須一致。 關閉httponly引起的問題 場景1: 測試A:咦,為什么test環境登錄不了呢? 程序員:清緩存。 測試B:握草,dev也登錄不了。。。誰看看! 程序員:清緩存。 測試們:。。。唉 場景...
摘要:所以,雖然接口正確返回了,但是由于跨域限制取不到這個值。這個需要在中深層次跨域設置。第一個想到的就是在父級的中加入設置。找了半天,最后找到一個不是很完美的解決方案,就是在里邊加入了跨域的設置。因為開發原則是盡量不要動包。 1.一般的跨域get和post,通過設置nginx就可以解決。在nginx.conf的http中加入以下代碼即可 add_header Access-Control-...
摘要:而我的新輪子也并不是專門解決它的問題的,而是順便解決而已。概述這個包,支持在所有的項目中使用。一旦出現成員,代表允許全部。列出允許跨域請求的方法列表,默認是代表所有方法。信息地址嗯,新輪子,求一波。 showImg(https://segmentfault.com/img/bV5VxN?w=844&h=656); 是的,可能了解 Laravel 的都知道,在 Laravel 中簡單的設...
摘要:但是隨著互聯網的發展,同源策略嚴重影響了項目之間的連接尤其是大項目,有幾個域名需要進行溝通的,標準推出了跨來源資源共享。 同源策略相信各位同學已然不陌生了,在這里不做過多闡述,簡單介紹一下就好: URL 說明 是否允許 http://www.a.com/a.js?/ http://www.a.com/b.js 同一域名下 允許 http://www.a.com/la...
摘要:于是乎同源策略應運而生主要限制在于和無法讀取。怎么繞過同源策略首先一般來說協議和端口造成的跨域問題大部分方法是沒有辦法繞過的。二級域名是寄存在主域名之下的域名。當主域名受到懲罰二級域名也會連帶懲罰。 前言 這是一道前端跨不過躲不掉面試必備的知識,掙扎多年沒能做到刻骨銘心深入脊髓,只能好好寫篇博文記錄起來了; 什么是跨域? 廣義來說,A域執行的文檔腳本試圖去請求B域下的資源是不被允許的,...
閱讀 2964·2021-09-23 11:32
閱讀 2931·2021-09-22 15:12
閱讀 1712·2019-08-30 14:07
閱讀 3455·2019-08-29 16:59
閱讀 1646·2019-08-29 11:11
閱讀 2311·2019-08-26 13:50
閱讀 2430·2019-08-26 13:49
閱讀 2625·2019-08-26 11:49