最近在學習http的相關知識,看到有關跨域的問題。平時工作中也會一直聽到跨域問題,自己就深入的學習一下,這里記錄一下,方便以后查閱。
1、為什么會出現跨域?
瀏覽器遵循同源政策(scheme(協議)
、host(主機)
和port(端口)
都相同則為同源
)。
非同源站點有這樣一些限制:
- 不能讀取和修改對方的 DOM
- 不讀訪問對方的 Cookie、IndexDB 和 LocalStorage
- 限制 XMLHttpRequest 請求。(后面的話題着重圍繞這個)
當瀏覽器向目標 URl 發 Ajax 請求時,只要當前 URL 和目標 URL 不同源,則產生跨域,被稱為跨域請求
。
2、解決方法
- JSONP
- CORS(跨域資源共享)
- Nginx
這里簡單的介紹一下前兩種方法:
【1】JSONP(參考文章)
JSONP 是服務器與客戶端跨源通信的常用方法。最大特點就是簡單適用,兼容性好(兼容低版本IE),缺點是只支持get請求,不支持post請求。
在HTML標簽里,一些標簽比如script、img這樣的獲取資源的標簽是沒有跨域限制的。
核心思想:網頁通過添加一個<script>元素
,向服務器請求 JSON 數據,服務器收到請求后,將數據放在一個指定名字的回調函數的參數位置傳回來。
【2】CORS(參考文章)
- 普通跨域請求:只需服務器端設置Access-Control-Allow-Origin
- 帶cookie跨域請求:前后端都需要進行設置(前端設置:根據xhr.withCredentials字段判斷是否帶有cookie)
本篇主要介紹React項目中的解決辦法:proxy與ngnix。
3、proxy
在package.json文件中使用proxy配置可以解決跨域問題.
"proxy":{ "/api":{ "target":"http://xxx.xxx.com", "changeOrigin": true, "pathRewrite": { "^/api": "" } } }
target
:接口的域名changeOrigin
:開啟代理pathRewrite
:可以看到我使用了/api
來匹配請求接口的域名,而接口名稱是/admin/login
,因此在實際請求中應該寫成/api/admin/login
,但是我實際請求的地址又是沒有api前綴的,因此需要通過pathRewrite重寫地址,將接口請求的時候前綴去除。
4、nginx
上面的方式可以解決我們在React項目中開發環境的跨域問題,但是無法解決生產環境上的跨域問題(偶爾也會遇見) 。
- Mac安裝nginx以及⚠️注意事項:請查看下篇文章
- 功能:
- http服務器,可以獨立提供http服務;
- 虛擬主機:多個域名指向同一個服務器,服務器根據不同的域名把請求轉發到不同的應用服務器;
- 反向代理:負載均衡,將請求轉發至不同的服務器
3. 默認配置文件
location / {
root html; #文件根目錄
index index.html index.htm; #默認起始頁
}
4.修改配置文件
location / { root /Users/zhangsan/Documents/test/build; #直接指向打包后的文件 index index.html index.htm; } location /api { rewrite ^.+api/?(.*)$ /$1 break; proxy_pass http://XX.XXX.com; # 將地址代理到api上 }