天天看點

解決前後端分離的跨域問題

 參考:https://mp.weixin.qq.com/s?__biz=MjM5NTM1NDcyOQ==&mid=202557064&idx=1&sn=d24349248e5dd70e0d0bcdc0fb6e6ca5#rd

https://blog.csdn.net/zhang6622056/article/details/75221492

   跨域是網絡安全領域的一個專有名詞。簡單點了解就是某些操作越過了域名的界限,通路了别的域名。如果腳本可以自由通路其他域,就會産生很多安全問題。

     什麼情況下會跨域? 不同協定、不同域名、不同端口、不同主機。

     什麼情況不是跨域?  滿足域名、協定、端口均相同的即不是跨域。

解決方案:

1、jsonp(不推薦)

  最初用來解決跨域問題的方式,叫做JSONP,它的基本原理是:跨域的“資源嵌入”是被浏覽器允許的。是以,可以通過一個script标簽來嵌入一段來自其他伺服器的腳本。由于這個腳本完全運作在目前域,無法通路第三方伺服器的cookie等敏感資訊,是以是安全的。

     JSONP的缺點是它隻能支援GET操作,沒法支援POST等操作,但是由于相容性好等優點,仍然有很多網站采用JSONP的方式公開自己的API供第三方調用。

2、反向代理

      要想解決跨域問題,最簡單徹底的方法當然是把他們拉到一個域下,而這就是該“反向代理”發揮作用的時候了。

   所謂反向代理,就是在自己的域名下架設一個Web伺服器,這個伺服器會把請求轉發給第三方伺服器,然後把結果傳回給用戶端。這時候,在用戶端看來,自己就是在和這台反向代理伺服器打交道,而不知道第三方伺服器的存在。

   是以,如果有一個Web服務程式,它同時提供了反向代理功能和靜态檔案服務功能,靜态檔案服務負責渲染前端頁面,反向代理則提供對第三方伺服器的透明通路。那麼前端和後端就變成了同源的,不再受同源政策的限制。

  那麼,有這樣的Web服務程式嗎?有,而且不止一個。事實上,幾乎所有的主流Web伺服器都提供了反向代理功能。這裡僅以nginx為例來示範反向代理的配置方式,其他Web伺服器請搜相應的文檔自行研究。

server {
    listen 80;
    server_name your.domain.name;
    location / {
        proxy_pass http://localhost:5000/; # 把根路徑下的請求轉發給前端工具鍊(如gulp)打開的開發伺服器,如果是産品環境,則使用root等指令配置為靜态檔案伺服器
    }
    location /api/ {
        proxy_pass http://localhost:8080/service/; # 把 /api 路徑下的請求轉發給真正的後端伺服器
        proxy_set_header Host $http_host;  # 把host頭傳過去,後端服務程式将收到your.domain.name,否則收到的是localhost:8080
        proxy_cookie_path /api /service;   # 把cookie中的path部分從/api替換成/service
        proxy_cookie_domain localhost:8080 your.domain.name; # 把cookie的path部分從localhost:8080替換成your.domain.name
    }
}
           

   注意最後這兩句話,由于cookie中存在一個path機制,可以對同一個域下的不同子域進行區分。是以,如果後端所使用的路徑是

/service

,而前端使用的路徑是

/api

,那麼前端将不能通路後端的cookie,這就導緻登入等操作所寫入的cookie無法正常傳入傳出,其表現則是登入始終沒有效果。cookie的domain機制也是類似的原理。

現實中的後端伺服器,使用path機制的很多,是以這項設定非常實用。

server {
        listen       80;
        server_name  domain.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        location /client { #通路用戶端路徑
            proxy_pass http://localhost:81;
            proxy_redirect default;
        }
        location /apis { #通路伺服器路徑
            rewrite  ^/apis/(.*)$ /$1 break;
            proxy_pass   http://localhost:82;
       }
}
           

3、CORS方式 

    這是W3C提供的另一種跨域方式。它定義了在跨域通路資源時浏覽器和伺服器之間如何通信。CORS背後的基本思想是使用自定義的HTTP頭部允許浏覽器和伺服器互相了解對方,進而決定請求或響應成功與否。

    作為一項标準的跨域規範,CORS本應該是最值得采用的。 問題在于,老式浏覽器不支援CORS,而我們顯然還沒到可以無視老式浏覽器的時候。 是以,隻要有可能,就應該優先采用反向代理的方式。

    CORS的原理是基于服務方授權的模式,也就是說提供服務的程式要主動通過CORS回應頭來聲明自己信任哪些源(協定+域名+端口)。 由于得到了服務方的授權,浏覽器就可以放行來自這些域的請求了。