精选文章 什么是跨域?怎么解决跨域问题?
一、什么是跨域
跨域,指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript施加的安全限制。
所謂同源是指,域名,協(xié)議,端口均相同,不明白沒關(guān)系,舉個栗子:
-
http://www.123.com/index.html 調(diào)用 http://www.123.com/server.PHP (非跨域)
-
http://www.123.com/index.html 調(diào)用 http://www.456.com/server.php
(主域名不同:123/456,跨域) -
http://abc.123.com/index.html 調(diào)用 http://def.123.com/server.php
(子域名不同:abc/def,跨域) -
http://www.123.com:8080/index.html 調(diào)用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
-
http://www.123.com/index.html 調(diào)用 https://www.123.com/server.php(協(xié)議不同:http/https,跨域)
-
請注意:localhost和127.0.0.1雖然都指向本機,但也屬于跨域。
瀏覽器執(zhí)行javascript腳本時,會檢查這個腳本屬于哪個頁面,如果不是同源頁面,就不會被執(zhí)行。
- 同源策略限制內(nèi)容有:
- Cookie、LocalStorage、IndexedDB 等存儲性內(nèi)容
- DOM 節(jié)點
- AJAX 請求不能發(fā)送
二、前端的解決辦法
使用方式就不贅述了,但是要注意JSONP只支持GET請求,不支持POST請求。
JSONP原理
ajax請求受同源策略影響,不允許進(jìn)行跨域請求,而script標(biāo)簽src屬性中的鏈接卻可以訪問跨域的js腳本,利用這個特性,服務(wù)端不再返回JSON格式的數(shù)據(jù),而是返回一段調(diào)用某個函數(shù)的js代碼,在src中進(jìn)行了調(diào)用,這樣實現(xiàn)了跨域。
jsonp其實是一種特定的格式,一般是 fun(json格式參數(shù)),
服務(wù)端:
header('Content-type: application/json');//獲取回調(diào)函數(shù)名$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']); //json數(shù)據(jù)$json_data = '["customername1","customername2"]'; //輸出jsonp格式的數(shù)據(jù)echo $jsoncallback . "(" . $json_data . ")";客戶端:
function callbackFunction(result, methodName) {console.log(result[0]); };其實就是返回一個js文件,里面執(zhí)行了callbackFunction方法;因為引用js文件不存在跨域的問題,這樣問題就解決啦~~~
例如www.123.com/index.html需要調(diào)用www.456.com/server.php,可以寫一個接口www.123.com/server.php,由這個接口在后端去調(diào)用www.456.com/server.php并拿到返回值,然后再返回給index.html,這就是一個代理的模式。相當(dāng)于繞過了瀏覽器端,自然就不存在跨域問題。比如vue-cli中開啟代理服務(wù)器的方式。
- vue.config.js的配置
- nginx反向代理
實現(xiàn)原理類似于Node中間件代理,需要你搭建一個中轉(zhuǎn)nginx服務(wù)器,用于轉(zhuǎn)發(fā)請求。使用nginx反向代理實現(xiàn)跨域,是最簡單的跨域方式。只需要修改nginx的配置即可解決跨域問題,支持所有瀏覽器,支持session,不需要修改任何代碼,并且不會影響服務(wù)器性能。實現(xiàn)思路:通過nginx配置一個代理服務(wù)器做跳板機,反向代理訪問domain2接口,并且可以順便修改cookie中domain信息,方便當(dāng)前域cookie寫入,實現(xiàn)跨域登錄。將nginx目錄下的nginx.conf修改如下:
這樣我們的前端代理只要訪問 http:www.domain1.com:81/*就可以了。
- header(‘Access-Control-Allow-Origin:*’);//允許所有來源訪問
- header(‘Access-Control-Allow-Method:POST,GET’);//允許訪問的方式
三、后端的解決方式
- 關(guān)于cors
CORS(Cross-origin resource sharing),跨域資源共享。CORS 其實是瀏覽器制定的一個規(guī)范,瀏覽器會自動進(jìn)行 CORS 通信,它的實現(xiàn)則主要在服務(wù)端,它通過一些 HTTP Header 來限制可以訪問的域,例如頁面 A 需要訪問 B 服務(wù)器上的數(shù)據(jù),如果 B 服務(wù)器 上聲明了允許 A 的域名訪問,那么從 A 到 B 的跨域請求就可以完成。對于那些會對服務(wù)器數(shù)據(jù)產(chǎn)生副作用的 HTTP 請求,瀏覽器會使用 OPTIONS 方法發(fā)起一個預(yù)檢請求(preflight request),從而可以獲知服務(wù)器端是否允許該跨域請求,服務(wù)器端確認(rèn)允許后,才會發(fā)起實際的請求。在預(yù)檢請求的返回中,服務(wù)器端也可以告知客 戶端是否需要身份認(rèn)證信息。我們只需要設(shè)置響應(yīng)頭,即可進(jìn)行跨域請求。
雖然設(shè)置 CORS 和前端沒什么關(guān)系,但是通過這種方式解決跨域問題的話,會在發(fā)送請求時出現(xiàn)兩種情況,分別為簡單請求和復(fù)雜請求。
- 簡單請求:
只要同時滿足以下兩大條件,就屬于簡單請求:
XMLHttpRequestUpload 對象均沒有注冊任何事件監(jiān)聽器; XMLHttpRequestUpload 對象可以使用
XMLHttpRequest.upload 屬性訪問;
- 復(fù)雜請求:
不符合以上條件的請求就肯定是復(fù)雜請求了。 復(fù)雜請求的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱為"預(yù)檢"請求,該請求是 option 方法的,通過該請求來知道服務(wù)端是否允許跨域請求。我們用PUT向后臺請求時,屬于復(fù)雜請求,后臺需被請求的Servlet中添加Header設(shè)置,Access-Control-Allow-Origin這個Header在W3C標(biāo)準(zhǔn)里用來檢查該跨域請求是否可以被通過,如果值為*則表明當(dāng)前頁面可以跨域訪問。默認(rèn)的情況下是不允許的。
這個方法僅對Java有用。springboot中,在Controller類上添加一個 @CrossOrigin(origins ="*") 注解就可以實現(xiàn)對當(dāng)前controller 的跨域訪問了,當(dāng)然這個標(biāo)簽也可以加到方法上,或者直接加到入口類上對所有接口進(jìn)行跨域處理,注意這個注解只在JDK1.8版本以上才起作用。
服務(wù)網(wǎng)關(guān)(zuul)又稱路由中心,用來統(tǒng)一訪問所有api接口,維護(hù)服務(wù)。Spring Cloud Zuul通過與Spring Cloud Eureka的整合,實現(xiàn)了對服務(wù)實例的自動化維護(hù),所以在使用服務(wù)路由配置的時候,我們不需要向傳統(tǒng)路由配置方式那樣去指定具體的服務(wù)實例地址,只需要通過Ant模式配置文件參數(shù)即可。當(dāng)然SpringCloud網(wǎng)關(guān)和微服務(wù)調(diào)用中心不只有這一種組合。
四、總結(jié)
- CORS支持所有類型的HTTP請求,是跨域HTTP請求的根本解決方案
- JSONP只支持GET請求,JSONP的優(yōu)勢在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請求數(shù)據(jù)。
- 不管是Node中間件代理還是nginx反向代理,主要是通過同源策略對服務(wù)器不加限制。
日常工作中,用得比較多的跨域方案是cors和nginx反向代理
參考文章
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的精选文章 什么是跨域?怎么解决跨域问题?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020中国硬科技创新白皮书
- 下一篇: 分布式事务原理