溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么解決js跨域問題

發(fā)布時(shí)間:2021-11-16 17:11:27 來源:億速云 閱讀:128 作者:小新 欄目:云計(jì)算

這篇文章主要介紹怎么解決js跨域問題,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

Js跨域問題是web開發(fā)人員最常碰到的一個(gè)問題之一。所謂js跨域問題,是指在一個(gè)域下的頁面中通過js訪問另一個(gè)不同域下的數(shù)據(jù)對(duì)象,出于安全性考 慮,幾乎所有瀏覽器都不允許這種跨域訪問,這就導(dǎo)致在一些ajax應(yīng)用中,使用跨域的web service會(huì)成為一個(gè)問題。 解決js跨域問題,目前在客戶端和服務(wù)端都有一些現(xiàn)成的解決方案,但這些方案并不能解決所有問題。下面我們先來看下有哪些常用的解決方案,并針對(duì)空間產(chǎn)品 對(duì)跨域問題的需求給出一個(gè)space自己的解決方案,希望能對(duì)其他產(chǎn)品組有借鑒意義。
客戶端解決方案
如何在客戶端解決js跨域問題幾乎是所有web開發(fā)人員會(huì)首先考慮的。目前最常用的方法有2種:設(shè)置document.domain、通過script 標(biāo)簽加載。
設(shè)置document.domain
采用這種方法的前提是跨域請(qǐng)求涉及的兩個(gè)頁面必須屬于一個(gè)基礎(chǔ)域(例如都是xxx.com,或是xxx.com.cn),使用同一協(xié)議(例如都是 http)和同一端口(例如都是80)。例如,aaa.xxx.com里面的一個(gè)頁面需要調(diào)用bbb.xxx.com里的一個(gè)對(duì)象,則將兩個(gè)頁面的 document.domain都設(shè)置為xxx.com,就可以實(shí)現(xiàn)跨域調(diào)用了。 另外,需要注意的是,這種方式只能用在父、子頁面之中,即只有在用iframe進(jìn)行數(shù)據(jù)訪問時(shí)才有用。
通過script標(biāo)簽加載
對(duì)于瀏覽器來說,script標(biāo)簽的src屬性所指向資源就跟img標(biāo)簽的src屬性所指向的資源一樣,都是一個(gè)靜態(tài)資源,瀏覽器會(huì)在適當(dāng)?shù)臅r(shí)候自動(dòng)去加 載這些資源,而不會(huì)出現(xiàn)所謂的跨域問題。這樣我們就可以通過該屬性將要訪問的數(shù)據(jù)對(duì)象引用進(jìn)當(dāng)前頁面而繞過js跨域問題。 例如,在space的我的空間項(xiàng)目中,需要在hi域下管理中心頁面中隨機(jī)推薦幾個(gè)熱門模塊給用戶,由于熱門模塊的相關(guān)信息都在act域下的php模塊中維 護(hù),如果直接在hi域下通過ajax請(qǐng)求去獲取act域下的推薦模塊列表相關(guān)信息就出現(xiàn)js跨域問題。解決這個(gè)問題的最簡單方法就是,在hi域下通過 script標(biāo)簽去訪問act域提供的這個(gè)http接口:
<script type=”text/javascript” src=http://www.2cto.com/kf/201109/”http://act.hi.baidu.com/widget/recommend”><script>
當(dāng)然,前提是act域的這個(gè)http接口必須是返回一段js腳本,如一個(gè)json對(duì)象數(shù)組定義的腳本:
modlist = [
{“modname” : “mod1”,  “usernum” : 200, “url” : ” /widget/info/1”},
{“modname” : ”mod2”,  “usernum” : 300, ”url” : ” /widget/info/2”},

];
但script標(biāo)簽也有一定的局限性,并不能解決所有js跨域問題。script標(biāo)簽的src屬性值不能動(dòng)態(tài)改變以滿足在不同條件下獲取不同數(shù)據(jù)的需求, 更重要的是,不能通過這種方式正確訪問以xml內(nèi)容方式組織的數(shù)據(jù)。
服務(wù)端解決方案
從上面的說明可以看到,客戶端的解決方案局限性太大,而且對(duì)于ajax跨域請(qǐng)求,無論兩個(gè)域是否屬于同個(gè)基礎(chǔ)域,都無法在客戶端加以解決。也就是說,如果 我們要想在ajax請(qǐng)求中訪問其他域下的數(shù)據(jù),就只能通過服務(wù)端進(jìn)行處理了。 服務(wù)端的解決方案的基本原理就是,由客戶端將請(qǐng)求發(fā)給本域服務(wù)器,再由本域服務(wù)器的代理來請(qǐng)求數(shù)據(jù)并將響應(yīng)返回給客戶端。 最常用的服務(wù)器解決方案就是利用web服務(wù)器本身提供的proxy功能,如apache和lighttpd的mod_proxy模塊。在百度內(nèi) 部,transmit的分流功能也可以解決部分跨域問題。但這些方法都有一定的局限性,鑒于安全性等問題的考慮,space這邊最后開發(fā)了一個(gè)專門用于處 理跨域請(qǐng)求代理服務(wù)的spproxy模塊,用于徹底解決js跨域問題。 下面我們將以空間的開放平臺(tái)為例,簡單介紹下如何通過apache的mod_proxy、transmit的分流以及space的spproxy模塊來解 決該跨域問題,并簡單介紹下spproxy的一些特性、缺點(diǎn)及下一步的改進(jìn)計(jì)劃。 空間在展現(xiàn)每個(gè)UWA開放模塊之前都必須請(qǐng)求該模塊的xml源代碼以進(jìn)行解析,每個(gè)模塊的源代碼文件都是存放在act域下的/ow/uwa目錄下,那么在 用戶空間首頁(hi域)中請(qǐng)求該xml文件時(shí)就會(huì)存在js跨域問題。要解決該問題,只能讓js向hi域的web服務(wù)器請(qǐng)求xml文件,而hi域web服務(wù) 器則通過一定的代理機(jī)制(如mod_proxy、transmit分流、spproxy)向act域的web服務(wù)器請(qǐng)求文件。
利用apache的mod_proxy模塊
如果apache是2.0系列版本,則可以通過在httpd.conf文件中增加以下配置加以解決:
ProxyRequests  Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass  /ow/uwa  http://act.hi.baidu.com/ow/uwa
其中,ProxyRequests 指令關(guān)閉了mod_proxy的正向代理功能而啟用反向代理功能,Proxy指令使得該配置對(duì)所有訪問生效,ProxyPass指令使得對(duì)本域的/ow /uwa目錄下的任何資源的訪問都會(huì)在內(nèi)部被轉(zhuǎn)換為一個(gè)對(duì)act.hi.baidu.com域下的/ow/uwa目錄下對(duì)應(yīng)資源的代理請(qǐng)求。 這樣,js就可以直接通過訪問http://hi.baidu.com/ow/uwa/0/1/0/10001.xml 獲取位于act域下的/ow/uwa/0/1/0/目錄下的10001.xml文件。
如果apache是經(jīng)過百度各產(chǎn)品線修改過的1.3版本,則需要mod_proxy和mod_rewrite模塊一起配合來達(dá)到同樣的目的。首先需要在 httpd.conf中增加以下Location指令:
<Location /ow/uwa>
SetHandler proxy-server
order allow,deny
Allow from all
</Location>
這樣,對(duì)于本域下的/ow/uwa目錄下的任何資源的訪問都會(huì)首先由proxy-server這個(gè)handler(mod_proxy模塊內(nèi)部定義的一個(gè) handler)來處理,但光有這段配置還不行,因?yàn)檫€不proxy-server還不知道應(yīng)該怎么處理,僅僅知道需要自己處理而已。這時(shí)還需要在配置段中增加一個(gè)rewrite規(guī)則:
RewriteRule ^/ow/uwa/(.*)$  http://act.hi.baidu.com/ow/uwa/$1?%{QUERY_STRING} [P,L]
Rewrite規(guī)則最后的[P,L]表明該rewrite是通過mod_proxy代理過去,而不是通過外部重定向過去。如果去掉P標(biāo)志,即采用以下 rewrite規(guī)則:
RewriteRule ^/ow/uwa/(.*)$  http://act.hi.baidu.com/ow/uwa/$1?%{QUERY_STRING} [L]
則響應(yīng)返回給客戶端時(shí)標(biāo)明的資源uri將是重定向后的uri,在我們的例子中就是act.hi.baidu.com域的uri,則瀏覽器仍然會(huì)出現(xiàn) js跨 域問題。 以上只是對(duì)apache的proxy功能的簡單應(yīng)用,更好更強(qiáng)大的介紹可以參考資料【1】和【2】。 Mod_proxy雖然強(qiáng)大,但我們并沒有用它來解決跨域問題。首先,要使用它必須要求我們的每臺(tái)前端機(jī)器都能夠訪問外網(wǎng),否則我們就只能將請(qǐng)求代理到其 中一臺(tái)前端機(jī)器上(通過機(jī)器名做內(nèi)網(wǎng)域名進(jìn)行rewrite或代理),而這顯然是不可取的,因?yàn)槲覀兊囊粋€(gè)域名通常由很多前端機(jī)器組成,只代理到其中一臺(tái) 機(jī)器會(huì)導(dǎo)致該機(jī)器壓力與其他機(jī)器相比很不均衡,甚至撐不住壓力,而給所有前端機(jī)器都加訪問外網(wǎng)權(quán)限又可能會(huì)存在一些安全性策略問題(具體原因不清楚,但 op和sa顯然是不會(huì)贊同這種做法)。其次,由于apache本身并沒有很好的防ddos***機(jī)制,一旦有人通過代理去***目標(biāo)域(比如說我們的競爭對(duì)手 的網(wǎng)站),則在目標(biāo)域的web服務(wù)器上看來,***者就成了我們了,這樣的事情發(fā)生時(shí),我們就百口莫辯,跳進(jìn)黃河也洗不清了。

以上是“怎么解決js跨域問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI