一、什么是跨域?
答:當前發起請求的域和該請求指向的資源所在的域不一致。具體表現在協議、域名、端口號——均一致為同域,有一個不同就是跨域。
--------------------------------------------------------------------------------------------------------------------------------
二、為什么要跨域?
答:①在前端開發中,經常需要到調用第三方服務接口;
②現在的項目大多采用前后端分離的模式,前端后端的域名不一致,因此需要解決跨域問題。
--------------------------------------------------------------------------------------------------------------------------------
三、解決“跨域”的五種常見方式:
注意:常見的html標簽中的“img”、“script”、“form”、“link”、“iframe”標簽發起請求時不存在跨域問題的限制。
1. JSONP
——根據“script”標簽發送請求時不存在跨域問題,在“script”標簽中發送相關請求
原理:①客戶端在script標簽中發送相關請求,並同時傳遞一個函數func;
②服務器端接收請求后,將准備好的數據data以“func(”+data+")"的形式發送給客戶端
③客戶端接收到“func(”+data+")"相關處理后,即執行函數func(data)
注意:由於JSONP基於script標簽,因而只能處理get請求、無法處理post請求。
---------------------------------------------------------------------------------------------------------------
2. CORS跨域資源共享
與JSONP對比更有優勢,無請求方式的局限性(post、get均可)。
客戶端:與正常非跨域請求相同;
服務端:設置相關的請求header頭部信息(注意需要處理options試探性請求)
---------------------------------------------------------------------------------------------------------------
3. http proxy代理跨域(利用Webpack配置):推薦使用。
優點:只需要在webpack.config.js文件中進行相關配置,無需其它編碼,操作簡單。
---------------------------------------------------------------------------------------------------------------
4. nginx反向代理
客戶端發送的請求不是直接到達目的服務器,而是到達部署在目的服務器端的代理服務器,通過代理服務器轉發接口請求,通過一定的轉發規則將接口請求轉發到目的服務器。
原理:
① 發送請求訪問8081.max.com,通過本地host文件域名解析,找到192.168.72.49服務器(安裝nginx)
② nginx反向代理接受客戶端請求,找到server_name為8081.max.com的server節點,根據proxy_pass對應的http路徑,將請求轉發到端口號為8081的tomcat服務器。
前端發送請求時跟非跨域時一致,只需要在服務器端安裝、配置nginx相關。
server {
listen 3000;
server_name localhost;
#將所有localhost:3000/為開頭的請求轉發
location / {
proxy_pass http://localhost:3001; //反向代理
index index.html index.htm;
#下面這兩條配置,意思是將http頭轉發給后端以拿到客戶端IP地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
另,為什么稱作“反向代理”?
正向代理:代理服務器代理的是客戶端。例如找一個代理服務器訪問Google,客戶端明確地指定要訪問的目的服務器,而目的服務器並不知道客戶端來源,在正向代理中客戶端信息是被隱藏的。
反向代理:代理服務器代理的是目的服務器,代理服務器與目的服務器同屬一個環境。發送請求的客戶端是明確的,但請求具體由哪台服務器處理並不明確,且代理服務器對外透明,客戶端並不知道自己訪問的是代理服務器,在反向代理中服務端被隱藏。
---------------------------------------------------------------------------------------------------------------
5. postMessage——基於iframe標簽
即window.postMessage() 方法,使用詳情見:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
---------------------------------------------------------------------------------------------------------------
6. socket.io ——實時通信聊天
使用詳情見:https://socket.io/get-started/chat