什么是跨域
不同域名之間相互請(qǐng)求資源,就是跨域。常說(shuō)的跨域問(wèn)題,指的是瀏覽器不允許跨域請(qǐng)求。這是由于瀏覽器的同源策略造成的蒿褂,是瀏覽器對(duì)JavaScript施加的安全限制。
其中同源指的是瞧毙,域名惯裕、協(xié)議、端口號(hào)都相同撞牢。例如對(duì)于 http://abc.123.com:8080/index/asddf 這樣一個(gè)網(wǎng)址來(lái)說(shuō)率碾,http/https是協(xié)議,abc.123.com是域名屋彪,8080是端口號(hào)所宰。而第一個(gè)單獨(dú)的反斜杠'/'后的內(nèi)容,并不影響是否是同源判斷畜挥。
瀏覽器之所以要限制跨域訪問(wèn)仔粥,是因?yàn)檫@種方式存在巨大的安全隱患。會(huì)造成CSRF(Cross-site request forgery)攻擊蟹但,也就是跨站請(qǐng)求偽造躯泰。攻擊者可以盜用你的身份,發(fā)送惡意請(qǐng)求华糖,威脅隱私和財(cái)產(chǎn)安全麦向。
跨域方案解決
1.反向代理
因?yàn)檫@是瀏覽器對(duì)于js的限制。所以在獲取其他域名下的內(nèi)容時(shí)缅阳,在自己的域名下架設(shè)一個(gè)Web服務(wù)器(ASP磕蛇、PHP、JAVA等)來(lái)獲取其他域名下的內(nèi)容十办,再將內(nèi)容返回前端秀撇。這樣通過(guò)js請(qǐng)求的內(nèi)容在同一域名下,就不會(huì)出現(xiàn)跨域的問(wèn)題向族。這也是跨網(wǎng)站請(qǐng)求數(shù)據(jù)常用的一種方法呵燕。
2.JSONP(只支持get)
JSONP是最初用來(lái)解決跨域問(wèn)題的方式。它的原理是跨域的“資源嵌入”是被瀏覽器允許的件相,用<script>標(biāo)簽沒(méi)有跨域限制的“漏洞”來(lái)達(dá)到與第三方通訊的目的再扭。這是一種非正式傳輸協(xié)議,通過(guò)一個(gè)script標(biāo)簽來(lái)指向一個(gè)來(lái)自其他服務(wù)器的API夜矗,并提供一個(gè)回調(diào)函數(shù)來(lái)接收數(shù)據(jù)泛范。被請(qǐng)求的服務(wù)器將需要返回的json數(shù)據(jù),放在回調(diào)函數(shù)位置返回紊撕。JSONP的缺點(diǎn)是它只能支持GET操作罢荡,沒(méi)法支持POST等操作。
3.CORS (Access-Control-Allow-Origin只能配置 一個(gè)域名或者* || 根據(jù)頭來(lái)動(dòng)態(tài)判斷更改)
CORS的原理是基于服務(wù)方授權(quán)的模式,也就是說(shuō)提供服務(wù)的程序要主動(dòng)通過(guò)CORS回應(yīng)頭來(lái)聲明自己信任哪些源(協(xié)議+域名+端口)区赵。 由于得到了服務(wù)方的授權(quán)惭缰,瀏覽器就可以放行來(lái)自這些域的請(qǐng)求了。
瀏覽器在發(fā)送請(qǐng)求時(shí)笼才,會(huì)在 Header 中加上一個(gè) origin(protocal + host + path + port) 字段漱受,來(lái)標(biāo)明這個(gè)請(qǐng)求是來(lái)自哪里。在服務(wù)端拿到這個(gè)請(qǐng)求之后骡送,會(huì)對(duì) origin 進(jìn)行判斷昂羡,如果是在允許范圍內(nèi)的請(qǐng)求,將會(huì)在 respones 返回的 Header 中加上:
Access-Control-Allow-Origin: origin
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: something
(1)Access-Control-Allow-Origin
該字段是必須的各谚。它的值要么是請(qǐng)求時(shí)Origin字段的值紧憾,要么是一個(gè),表示接受任意域名的請(qǐng)求昌渤。
(2)Access-Control-Allow-Credentials
該字段可選赴穗。它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie膀息。默認(rèn)情況下般眉,Cookie不包括在CORS請(qǐng)求之中。設(shè)為true潜支,即表示服務(wù)器明確許可甸赃,Cookie可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器冗酿。這個(gè)值也只能設(shè)為true埠对,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可裁替。
(3)Access-Control-Expose-Headers
該字段可選项玛。CORS請(qǐng)求時(shí),XMLHttpRequest對(duì)象的getResponseHeader()方法只能拿到6個(gè)基本字段:Cache-Control弱判、Content-Language襟沮、Content-Type、Expires昌腰、Last-Modified开伏、Pragma。如果想拿到其他字段遭商,就必須在Access-Control-Expose-Headers里面指定固灵。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值劫流。
所以巫玻,在服務(wù)端可以通過(guò)設(shè)置“Access-Control-Allow-Origin”來(lái)指定允許跨域訪問(wèn)的域名暑认。這里有一個(gè)問(wèn)題就是設(shè)置Access-Control-Allow-Origin只能配置 一個(gè)域名或者 。那么有多個(gè)域名允許訪問(wèn)但并不是允許所有訪問(wèn)怎么辦呢大审。這個(gè)時(shí)候可以在獲取到請(qǐng)求時(shí),判斷其域名是否允許訪問(wèn)座哩,如果允許訪問(wèn)徒扶,動(dòng)態(tài)的將Access-Control-Allow-Origin允許的域名設(shè)置為網(wǎng)絡(luò)請(qǐng)求的域名。
4.瀏覽器配置跨域 (針對(duì)某一瀏覽器根穷,禁止其跨域的檢查)
前面說(shuō)到姜骡,跨域問(wèn)題實(shí)際上是瀏覽器對(duì)js的限制,那么我們只要把這個(gè)功能關(guān)掉就可以了屿良。但是這種方法適用性比較小圈澈,首先這種設(shè)置只針對(duì)某一瀏覽器,不同的瀏覽器設(shè)置是不同的尘惧;其次這個(gè)設(shè)置是跟瀏覽器綁定的康栈,A電腦的瀏覽器關(guān)閉了功能,可以跨域訪問(wèn)喷橙,但是其他電腦沒(méi)有設(shè)置過(guò)的瀏覽器還是不可以跨域訪問(wèn)啥么;最后這種設(shè)置是不安全的。所以這種方式一般只會(huì)在項(xiàng)目開(kāi)發(fā)時(shí)使用贰逾,特別是前后端分離開(kāi)發(fā)但是線上代碼在同一域名下時(shí)悬荣。這里提供chrome瀏覽器的設(shè)置方式
5.Vue-cli proxyTable 開(kāi)發(fā)環(huán)境跨域問(wèn)題
這里針對(duì)于Vue開(kāi)發(fā)項(xiàng)目前后端分離開(kāi)發(fā),實(shí)際線上代碼在同一域名下疙剑,即僅需要在開(kāi)發(fā)環(huán)境時(shí)設(shè)置跨域的情況氯迂。這里用到的是vue-cli中config文件的proxyTable設(shè)置。
這個(gè)參數(shù)主要是一個(gè)地址映射表言缤,你可以通過(guò)設(shè)置將復(fù)雜的url簡(jiǎn)化嚼蚀,例如我們要請(qǐng)求的地址是abc.sample.com/user/list,可以按照如下設(shè)置:
proxyTable: {
'/user': {
target: 'http://abc.sample.com',
changeOrigin: true,//解決跨域設(shè)置轧简,本地會(huì)虛擬一個(gè)服務(wù)端接收你的請(qǐng)求并代你發(fā)送該請(qǐng)求
pathRewrite: {
'^/user': '/user'
}
}
}
這樣之后驰坊,這樣我們?cè)趯憉rl的時(shí)候,只用寫成/user/list就可以代表abc.sample.com/user/list哮独。我們還可以這樣寫拳芙,將需要跨域的請(qǐng)求寫成/api/***,以上面為例就是/api/list/user皮璧,然后設(shè)置如下
proxyTable: {
'/api': {
target: 'http://abc.sample.com',
changeOrigin: true,//解決跨域設(shè)置舟扎,本地會(huì)虛擬一個(gè)服務(wù)端接收你的請(qǐng)求并代你發(fā)送該請(qǐng)求
pathRewrite: {
'^/api': '/' //實(shí)際請(qǐng)求是沒(méi)有api的,為了方便區(qū)分和匹配才加的悴务,所以這里將請(qǐng)求的/api重寫為/
}
}
}