因?yàn)闉g覽器可以同時(shí)打開很多頁面,可以同時(shí)保存很多授權(quán)信息,瀏覽器為了安全問題,采用了同源策略(瀏覽器存在跨域問題,服務(wù)器不存在跨域問題)
同源策略:是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSRF等攻擊。同源是指"協(xié)議+域名+端口"三者相同,即便兩個(gè)不同的域名指向同一個(gè)ip地址,也非同源。
比如,瀏覽器的地址是baidu.com,頁面通過ajax請求京東,就存在跨域,瀏覽器就阻止了該行為
現(xiàn)在有一個(gè)需求,兩個(gè)服務(wù)器A和B,瀏覽器通過請求服務(wù)器A獲取頁面A,然后在頁面A下通過ajax請求訪問網(wǎng)頁B,瀏覽器是不允許這樣操作的,但是可以通過一些條件可以去實(shí)現(xiàn)
1.瀏覽器的頁面A通過Ajax請求訪問B頁面時(shí),瀏覽器可以先詢問服務(wù)器B是否同意
如果頁面A通過ajax直接訪問頁面B,會報(bào)錯(cuò) cors -> cross origin resources sharing error,MissingAllowOriginHeader(跨域資源共享,丟失了允許跨域的頭)
解決方案:
@RestController
public class UserController {
//方式一:手動添加請求頭
@RequestMapping("/user")
public User getUser(HttpServletResponse response){
//第一個(gè)參數(shù)是添加一個(gè)請求頭,第二個(gè)參數(shù)是允許請求的來源地址
response.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8081");
//10秒鐘之內(nèi)再次請求的時(shí)候,就不用發(fā)送預(yù)檢請求了
response.addHeader("Access-Control-Max-Age", "10");
//允許你發(fā)送的請求是GET請求還是POST請求
response.addHeader("Access-Control-Allow-Method", "GET");
return new User("java", "java");
}
//方式二:添加注解@CROSSORIGIN
@RequestMapping("/user")
@CROSSORIGIN(origin = {"http://127.0.0.1:8081"})//添加來源地址
public User getUser(HttpServletResponse response){
return new User("java", "java");
}
}
瀏覽器的頁面A訪問頁面B的時(shí)候,會發(fā)送兩個(gè)請求,第一個(gè)請求是option——預(yù)檢請求,第二請求是get——獲取數(shù)據(jù)
2.服務(wù)器與服務(wù)器之間是不存在跨域問題的,因?yàn)闉g覽器可以同時(shí)打開十幾個(gè)網(wǎng)站,這時(shí),瀏覽器既有A頁面的授權(quán)信息,也有B頁面的授權(quán)信息,而服務(wù)器不可能打開十幾個(gè)網(wǎng)站,并獲取到別的頁面的授權(quán)信息,否則A網(wǎng)站就相當(dāng)于做了B網(wǎng)站的認(rèn)證了,瀏覽器使得客戶端能夠?qū)⒍鄠€(gè)網(wǎng)站的用戶信息都存在同一物理環(huán)境,而服務(wù)器只能保存自己所提供服務(wù)的信息
解決方案:瀏覽器通過網(wǎng)頁A訪問服務(wù)器A,服務(wù)器A再去訪問服務(wù)器B,這樣服務(wù)器A就相當(dāng)于一個(gè)中間代理,去獲取服務(wù)器B的網(wǎng)頁信息
實(shí)現(xiàn)一:可以通過http請求服務(wù)器B獲取網(wǎng)頁B的數(shù)據(jù),例如restTemplate,相當(dāng)于手寫一個(gè)方向代理服務(wù)器
實(shí)現(xiàn)二:nginx(方向代理,動靜分離,負(fù)載均衡),修改配置文件
server {
? ? ? ? listen ? ? ? 80;
? ? ? ? server_name ?localhost;
? ? ? ? ##添加以下標(biāo)紅的部分
? ? ? ? location /api {
? ? ? ? ? ? proxy_pass http://127.0.0.1:8082;? ? ##路徑帶有api的請求轉(zhuǎn)發(fā)到端口為8082的服務(wù)器
? ? ? ? }
? ? ? ? location / {
? ? ? ? ? ? root ? html;
? ? ? ? ? ? index ?index.html index.htm;
? ? ? ? }
? ? ? ? error_page ? 500 502 503 504 ?/50x.html;
? ? ? ? location = /50x.html {
? ? ? ? ? ? root ? html;
? ? ? ? }
? ? }
正向代理:用戶A訪問Google,由于存在墻,用戶A只能通過先訪問香港的服務(wù)器,由香港的服務(wù)器轉(zhuǎn)發(fā)請求到Google服務(wù)器,這種代理模式是,用戶明確要訪問的地址,由于無法直接訪問到最終的服務(wù)器,只能通過中間服務(wù)器去訪問,直接輸入Google的地址就可以了??
反向代理:用戶B訪問代理服務(wù)器,但是服務(wù)器B要訪問哪獲取數(shù)據(jù),用戶不知道
3.jsonp利用瀏覽器天然支持跨域的標(biāo)簽<script>
<script>標(biāo)簽天然支持跨域,只支持GET請求,例如
前端代碼
<script>
function callback(data){
console.log(data)
}
</script>
<script src="http://127.0.0.1:8082/cross"></script>
后端代碼
@RequestMapping("/cross")
public String cross(HttpServletResponse response){
return "callback('123')"
}
請求返回后,返回的字符串會調(diào)用前端方法cross,最終打印出123
當(dāng)使用script請求地址時(shí),會將返回的字符串,默認(rèn)當(dāng)成js解析。由于后端返回是的callback(xxx),所以會調(diào)用本地的callback函數(shù)。
從原理上來看,要使用JSONP,必須要后端返回相應(yīng)的數(shù)據(jù),這個(gè)就是JSONP的模式了,允許客戶端傳遞一個(gè)callback函數(shù),后端將數(shù)據(jù)包裹在callback函數(shù)中返回。文章來源:http://www.zghlxwxcb.cn/news/detail-477190.html
從原理也能看出,JSONP并不要求必須傳遞JSON格式的數(shù)據(jù),只要是JS函數(shù)能夠認(rèn)可的數(shù)據(jù)都是可以傳遞的文章來源地址http://www.zghlxwxcb.cn/news/detail-477190.html
到了這里,關(guān)于跨域解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!