CORS 请求未能成功_当遇到跨域开发时, 我们如何处理好前后端配置和请求库封装(koa/axios版)...
我們知道很多大型項目都或多或少的采用跨域的模式開發, 以達到服務和資源的解耦和高效利用. 在大前端盛行的今天更為如此, 前端工程師可以通過nodejs或者Nginx輕松搭建起web服務器.這個時候我們只需要請求后端服務器的接口即可實現系統的業務功能開發.這個過程中會涉及到web頁面向API服務器的跨域訪問(由于受到瀏覽器的同源策略,但是業界已有很多解決方案,接下來會介紹).通過這種開發模式使得我們真正的實現了前后端完全分離.
采用這種前后端單獨開發部署的模式好處有如下幾點: 減少后端服務器的并發/負載壓力 前端項目和后端項目完全分離, 一定程度上提高了自動化部署的靈活性, 并且代碼更易管理和維護 提高前后端開發團隊的工作效率, 各司其職, 出現bug更容易定位問題 在大并發情況下可以同水平擴展前后端服務器,利用多臺前端服務器做集群來抗住日均千萬級的pv 提高應用容錯, 即使是API服務器掛了, 前端頁面依然能正常訪問 API服務器能同時為多個應用平臺提供服務, 大量復用接口,提升效率。(比如說微服務)
雖然好處有很多, 但是為了實現以上的架構模式, 我們首先要解決的就是跨域問題.
瀏覽器的同源策略
同源策略是一個重要的安全策略,它用于限制一個origin的文檔或者它加載的腳本如何能與另一個源的資源進行交互。它能幫助阻隔惡意文檔,減少可能被攻擊的媒介。如果兩個URL的protocol(協議,比如http協議,https協議)、port (端口號,如80)和 host(主機,如http://developer.mozilla.org) 都相同的話,則這兩個 URL 是同源。這個方案也被稱為“協議/主機/端口元組”,或者直接是 “元組”。也就是說如果不滿足以上3個條件中的任意一個,則被視為跨域.
解決跨域問題的幾種方式
業界解決瀏跨域問題的方案很多, 筆者在這里粗略介紹一下: JSONP實現跨域 通過script標簽和url回調來實現跨域, 缺點是只支持get請求 CORS CORS需要瀏覽器和后端同時支持, 后端設置Access-Control-Allow-Origin 就可以開啟 CORS postMessage 可以實現跨文本檔、多窗口、跨域消息傳遞(筆者之前寫可插拔式聊天機器人就是采用該方案) websocket websocket是HTML5的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通信,也是跨域的一種解決方案 nginx反向代理 document.domain + iframe 比較傳統的跨域解決方案
目前作為大規模跨域開發使用最多的模式還是CORS方案,所以筆者接下來將具體介紹采用cors模式搭建前后端跨域訪問通用解決方案, 為了方便,筆者后端將采用nodejs+koa, (java/php開發類似), 前端采用axios作為請求庫來配合實現完整的cors模式.
跨域開發的后端配置(node/koa版)
要想徹底了解cors的跨域模式, 我們還是要深入實踐中來, 筆者將采用nodejs和koa中間件來實現cors模式的搭建.這里筆者先簡單介紹一下cors:
跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭 來告訴瀏覽器 讓運行在一個域上的Web應用被準許訪問來自不同源服務器上指定的資源。基本場景如下:
對于簡單的跨域場景,我們只需要設置請求頭的Access-Control-Allow-Origin字段即可, 比如設置為*號表示允許任何域名的訪問.
這里我們使用koa2-cors這個中間件來實現一下, 代碼如下:
import通過這樣的配置, 我們就能輕松實現cors跨域, 不過現實開發中我們一般不會這么設置, 因為這樣設置意味著任何人都能訪問我們的服務,安全性無法保證. 作為小型的開放服務,可以采用這樣的配置加上訪問限流來實現免費圖床類應用.(開放圖床實現可以參考筆者之前寫的文章
徐小夕:如何使用nodeJs開發自己的圖床應用??zhuanlan.zhihu.com)
在實際開發中, 我們會將origin的返回值設置為指定域名, 這樣就只允許該域名下的請求訪問, 所以正確的姿勢如下:
import通過這種方式, 我們在開發環境中, 可以讓前端同事自由訪問我們的API接口, 提高聯調效率, 而在生產環境中只允許我們的WEB服務器所在域名訪問.
更進一步
對于簡單請求和簡單的開發模式, 以上的設計就基本滿足要求了, 但是對于復雜的業務場景, 我們的請求模式往往會涉及到更多的要求, 比如說需要攜帶cookie, 用戶憑證或者自定義的請求頭信息等(比如典型的JWT認證的token一般會存放到自定義的頭信息中), 此時往往會發送預檢請求(要求必須先使用 OPTIONS 方法發起一個預檢請求到服務器,以獲知服務器是否允許該實際請求。"預檢請求“的使用,可以避免跨域請求對服務器的用戶數據產生未預期的影響).
這里我們需要了解以下幾個響應頭部的字段: Access-Control-Allow-Methods 表明服務器允許客戶端使用的請求方法 Access-Control-Allow-Headers 表明服務器允許請求中攜帶的頭部字段 Access-Control-Max-Age 表明響應的有效時間。在有效時間內,瀏覽器無須為同一請求再次發起預檢請求 Access-Control-Expose-Headers 服務器允許瀏覽器訪問的頭信息白名單 * Access-Control-Allow-Credentials 指定了當瀏覽器的credentials設置為true時是否允許瀏覽器讀取response的內容
以上這5個響應頭部字段非常重要,這也是我們解決復雜跨域場景的關鍵配置. 具體配置案例如下:
// 設置跨域以上是采用koa2-cors實現的方案, 通過設置exposeHeaders, 我們就可以在瀏覽器端拿到服務器響應的頭部字段'WWW-Authenticate', 'Server-Authorization', 'x-show-msg', 進而根據這些字段的值來實現定制化的消息機制.
需要注意的是, 我們服務器在設置credentials后,需要前端請求庫配置設置,比如我們需要在axios中設置withCredentials為true, 代碼如下:
import這樣我們就能成功攜帶用戶憑證并被跨域的后端服務器獲取了.以上就實現了我們cors模式的后端配置, 對于nodeJS為主的后端選手, 基本任務已經完成, 對于java/PHP選手, 也可以參考類似的配置和庫來實現. 接下來我們來實現前端請求庫的封裝.
跨域開發的前端請求庫封裝(axios版)
作為一名前端工程師, 沒有一個上手的請求庫是萬萬不行的, 目前業界比較好的輪子有axios, umi-request等, 但是后者在使用過程中有一些坑(畢竟基于fetch實現), 所以這里筆者將基于axios來簡單實現一個跨域請求庫的封裝.方便大家集成在自己的vue或者react項目中. 接下來看看請求庫封裝的簡單模型:
筆者將基于http規范的錯誤類型進行基本的消息系統設計, 代碼如下:
import以上筆者結合antd的message作為消息反饋UI,利用axios的請求和響應攔截來實現消息系統的設計, 以上只是基本的框架, 大家可以基于以上設計進行更加自定義的封裝.
講到這里, 大家是不是對跨域下的服務端和前端配置有了更進一步的了解了呢?
最后
如果想學習更多H5游戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰,歡迎在《趣談前端》專欄學習討論,共同探索前端的邊界。
更多推薦
徐小夕:如何用vue/react搭建我們的前端全棧CMS項目?zhuanlan.zhihu.com徐小夕:基于nodeJS從0到1實現一個CMS全棧項目(中)(含源碼)?zhuanlan.zhihu.com徐小夕:CMS全棧項目之Vue和React篇(下)(含源碼)?zhuanlan.zhihu.com徐小夕:從零到一教你基于vue開發一個組件庫?zhuanlan.zhihu.com徐小夕:如何從0到1教你搭建前端團隊的組件系統?zhuanlan.zhihu.com徐小夕:如何優雅的搭建nodejs開發環境及目錄設計??zhuanlan.zhihu.com徐小夕:徹底掌握redux并開發一個react實戰項目?zhuanlan.zhihu.com總結
以上是生活随笔為你收集整理的CORS 请求未能成功_当遇到跨域开发时, 我们如何处理好前后端配置和请求库封装(koa/axios版)...的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 操作系统:分享Win11几个实用小技巧,
 - 下一篇: Java技术:Spring Boot 配