跨域請求
Cross Origin Policy 是在瀏覽器實現(xiàn)的一個規(guī)則。這個規(guī)則規(guī)定不同源下的代碼不可以訪問比起的資源(包括網(wǎng)絡(luò)請求侄泽,靜態(tài)文件和本地緩存等)。對于是否同源的界定是:協(xié)議(http/https)孝凌,域名和端口误债。三個之中任意一個不同都不能算做同源。同源限制是瀏覽器為了保證數(shù)據(jù)安全而實現(xiàn)的規(guī)則迄埃。試想一下不同源的網(wǎng)站可以隨意的訪問彼此的數(shù)據(jù)疗韵,就毫無隱私安全可言了。
實現(xiàn)跨域請求
Jsonp: 利用JS標簽可以進行跨域請求的特性侄非,將跨域請求的鏈接賦值給
script
標簽的src
屬性蕉汪,同時在URL末尾添加callback
函數(shù)。當跨域請求完整之后逞怨,跨域的服務(wù)器會把JSON字符串包裹在回調(diào)函數(shù)中者疤,即callback({...})
,然后返回到前端叠赦,瀏覽器收到之后會嘗試將其轉(zhuǎn)化成JavaScript執(zhí)行驹马。所以你只需要在全局中定義callback
函數(shù)就可以接受數(shù)據(jù)了。
缺點:只支持get
請求除秀。需要后端的支持(返回函數(shù)的包裹等)糯累。代碼比較混亂。postMessage:主要用來支持前端不同頁面(不同源)之間的信息交互鳞仙。
CORS(Cross-Origin Resource Sharing): 跨域資源共享寇蚊。這是比較標準的跨域解決方案。CORS允許跨域請求的前提是棍好,當前域被目標域認可了(Access-Control-Allow-Origin)仗岸。如果當前域被目前域所認可允耿,瀏覽器就會允許當前域讀取返回的數(shù)據(jù)。
注意:無論當前域有沒有被認可扒怖,請求(Get和Option)是一定會被發(fā)出的空入,也一定會接受到response
沙兰,只是不能讀取而已。Nginx反向代理
Nginx反向代理實現(xiàn)跨域
反向代理
反向代理服務(wù)器的任務(wù)就是把接受到的請求再分派到其他的服務(wù)器中處理,處理完畢后再將結(jié)果返回窗悯,請求的一方并不知道最終是哪個服務(wù)器處理了自己的請求羽历。反向代理一般被用來分流均衡讲弄。
實現(xiàn)跨域
跨域最主要的問題就是瀏覽器對來自不同源的response進行阻隔扎拣。那么你只要讓瀏覽器相信請求的鏈接和當前域是同源的話,就可以解決跨域問題了稽鞭。
所以我們可以給前端App添加Nginx配置鸟整,然后劃分一個特定的子域名,例如/external_api/
朦蕴,用來專門接受對外服務(wù)的請求篮条,然后使用proxy_pass
將請求分發(fā)給外部的服務(wù)器,外部服務(wù)器處理完后將結(jié)果返回吩抓,Nginx在將結(jié)果當成自己處理的進行返回就可以了涉茧。所以這實際上也是繞開了同源規(guī)則的限制。
方法一: 為前端配置Nginx
這種方法是為前端應(yīng)用配置Nginx疹娶,使得對前端的訪問都先經(jīng)過Nginx的處理和轉(zhuǎn)發(fā)伴栓。這種方法有一個小缺點就是這個匹配對外請求的路徑/external_api/
會占用前端的路徑。
Nginx配置:
server {
location / {
# 正常匹配前端應(yīng)用的頁面資源蚓胸。
root /html;
index index.html index.htm;
}
//自定義本地路徑
location /external_api {
rewrite ^.+external_api/?(.*)$ /$1 break; # 刪除自定義的前綴挣饥。
include uwsgi_params; # 包含參數(shù)除师。
proxy_pass http://www.target.com; # 分發(fā)到目標服務(wù)器沛膳。
}
}
方法二: 創(chuàng)建一個新的Nginx服務(wù)器
這種方法和上面一種的區(qū)別在于:Nginx和前端App是分開存在的。Nginx在匹配到 location /
的時候汛聚,會把請求轉(zhuǎn)發(fā)到前端app锹安,而不是指向本地路徑。
Nginx配置:
server {
location / {
# 轉(zhuǎn)發(fā)到前端倚舀。
proxy_pass http://www.front-end.com;
}
//自定義本地路徑
location /external_api {
rewrite ^.+external_api/?(.*)$ /$1 break; # 刪除自定義的前綴叹哭。
include uwsgi_params; # 包含參數(shù)。
proxy_pass http://www.target.com; # 分發(fā)到目標服務(wù)器痕貌。
}
}