參考如下博客,自己小小總結了下跨域的一些問題:
什麼是跨域
瀏覽器爲什麼要設計同源策略
什麼是跨域?如何解決
跨域的概念
一個域下的文檔或者腳本(比如ajax) 去請求另外一個域的資源。
這裏判斷是否在一個域的,依據三點: 協議(http|https) + 域名 + 端口 ,如果中間 有任一個不同,那麼就算是跨域請求。
注意: 如果兩個域名指向同一個ip ,那也算是跨域請求!
我們來看下面的頁面是否與 http://store.company.com/dir/index.html 是同源的?
http://store.company.com/dir/index2.html 同源
http://store.company.com/dir2/index3.html 同源 雖然在不同文件夾下
https://store.company.com/secure.html 不同源 不同的協議(https)
http://store.company.com:81/dir/index.html 不同源 不同的端口(81)
http://news.company.com/dir/other.html 不同源 不同的域名(news)
跨域的原由
主要是因爲瀏覽器的設定了同源策略(SOP)。
不同的域下存着不同的數據,例如cookie 等,發送同域的請求,cookie 會自動攜帶上,如果是不同域的請求,因爲有了同源策略,那麼cookie 是無法攜帶的 且 發送不同域的請求也是被攔下來的。
思考一下,如果沒有SOP ,當請求到跨域的網站時,那個網站就能獲取到源網站的一些cookie 信息了,要知道 cookie 裏有時候存儲的都是用戶信息,比如sessionId , 若對方網站是一個惡意網站,很輕鬆地就能獲取到你的sessionId ,然後進行連接攻擊了。
注意: 一些加載圖片、js、css等資源是不違背同源策略的,比如 http://phone.happy.com 裏需要展示 http://img.happy.com/xxx.png 是可行的。如果是訪問接口 , 就可能違背。
跨域的實際例子
一個APP應用開發,前端使用H5 做頁面 , 後端提供APP的接口 即可。2個項目都部署到同一臺服務器上,分配不同域名,並且都部署到nginx上。
前端 | 後端 | |
---|---|---|
域名 | http://phone.happy.com | http://api.happy.com |
前端項目請求後端接口時,從http://phone.happy.com 訪問http://api.happy.com的時候,就是一個跨域請求,一般在瀏覽器F12模式下,可以看到類似類似類似下圖的錯誤日誌:
那麼如何解決這種問題呢?請耐心地看下文。
解決跨域的辦法
網上也有很多解決辦法,是從前端着手的。額,我自己的解決辦法就是通過Nginx的代理。當Nginx 接收到前端需要請求後端接口時,將前端請求轉到後端接口服務上即可。
需要注意的是,在我的後端接口項目的context-path 我設定的是 /happyapi (/+項目名+api),儘量和 前端 裏的一些路由不要衝突吧。
實戰
主要就是在nginx上配置下就好了
。。。省略
http{
#上游服務器-接口項目
upstream happyapi{
server localhost:9099 weight=1 max_fails=1 fail_timeout=3s;
}
#接口項目
server{
listen 80; #服務端口號,也就是nginx的port
server_name api.happy.com; #服務器的域名
location /{
proxy_pass http://happyapi; #轉到上游服務器
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
。。。省略
}
}
#前端H5項目
server{
listen 80;
server_name phone.happy.com;
#h5項目
location /{
root /usr/local/happy/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
#h5項目裏的字體格式
location ~* /.(eot|ttf|ttc|otf|eot|woff|woff2|svg)$ {
root /usr/local/happy/dist;
}
#攔截到api的請求,代理轉發到接口項目
location /happyapi/{
proxy_pass http://happyapi; #對應upstream
}
}
}
核心內容:
#攔截到api的請求,代理轉發到接口項目
location /happyapi/{
proxy_pass http://happyapi; #對應upstream
}
所以如果前端發送 http://phone.happy.com/happyapi/user/login 的請求時,Nginx 會攔截並轉發到 http://api.happy.com/happyapi/user/login 上 ,也就是真正的接口項目了。