摘要:我通過這篇文章把今天工作中遇到的跨域和請求的一個坑記錄下來。預檢請求機制的使用,是為了避免跨域請求對服務器的用戶數據產生未預期的影響。我使用了認證方式,這種方式不會造成該請求成為一個需要預檢的請求,所以最后跨域成功了。
我通過這篇文章把今天工作中遇到的HTTP跨域和OPTION請求的一個坑記錄下來。
場景是我需要在部署在域名a的Web應用里用JavaScript去消費一個部署在域名b的服務器上的服務。域名b上的服務也是我開發的,因此我將域名a加到了該服務的HTTP響應結構的頭文件里,這樣就允許了域名a上的JavaScript代碼用AJAX訪問域名b的服務。
域名b上的服務是一個Servlet,允許域名a跨域訪問的代碼就一行:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 做業務邏輯 response.setHeader("Access-Control-Allow-Origin", "域名a"); }
我在域名a的Web應用里用AJAX發起服務請求:
執行后,發現并沒有顯示200的彈出窗口。
錯誤消息:Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
觀察Chrome開發者工具,發現其實域名b的服務已經成功執行了,確實返回了200的Status code,
而且我已經從Chrome開發者工具里觀察到瀏覽器已經成功接到域名b發送回來的請求了。
那這個錯誤是什么鬼呢?根據錯誤消息“Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response” Google了一下,發現一些朋友遇到同樣的問題:
1.?如何解決出現AXIOS的Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
網頁地址: https://www.cnblogs.com/caimu...
這位朋友的解決方案:
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token"); response.setHeader("Access-Control-Expose-Headers", "*"); if (request.getMethod().equals("OPTIONS")) { HttpUtil.setResponse(response, HttpStatus.OK.value(), null); return; }
但我試過,在我的場景下還是不工作,因為我的例子里,服務器已經針對OPTIONS請求返回HTTP 200的狀態碼了。
2. 這個Stackoverflow的帖子里,很多朋友都提供了自己的解決方案。
https://stackoverflow.com/que...
我一一試過,在我的場景里都不能工作。
于是我查詢了Mozilla的一篇文檔:HTTP訪問控制(CORS)
https://developer.mozilla.org...
里面談到了,在某些情況下,瀏覽器在發起“需要預檢的請求”之前,必須首先發起一個“預檢請求(Preflight)”到服務器,以探測服務器是否允許這個實際請求。"預檢請求"機制的使用,是為了避免跨域請求對服務器的用戶數據產生未預期的影響。
那么哪些請求算作“需要預檢的請求”呢?Mozilla的這篇文檔定義得很清楚:
當請求滿足下述任一條件時,即應首先發送預檢請求:
使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
人為設置了對 CORS 安全的首部字段集合之外的其他首部字段。該集合為:
Accept
Accept-Language
Content-Language
Content-Type (but note the additional requirements below)
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 的值不屬于下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
我再檢查我的代碼,因為我在HTTP請求里用xhr.setRequestHeader("Authorization", "用戶名:密碼的base64編碼" )添加了用于Basic Authentication的頭部,因此迫使該請求成為了“需要預檢的請求”,所以才有了OPTION請求的發送。
現在我將其注釋掉:
這次遇到了401 Unauthorized錯誤了:
然而沒有預檢請求OPTION發出來了,請求類型變成了我期望的POST方式了。
但是現在就陷入了一個矛盾的境地:如果在請求頭部加上Basic Authentication的信息,會遇到錯誤消息“Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.”。如果去掉,雖然避免了預檢請求,但是又遇到401 Unauthorized錯誤了。
于是,我換了一種認證方式,終于成功實現了期望的跨域請求,在我域名a的前端應用里打印出了來自于域名b的服務的響應。
我使用了form認證方式,這種方式不會造成該請求成為一個”需要預檢的請求“,所以最后跨域成功了。
var formData = new FormData(); formData.append("sap-client", "001"); formData.append("sap-user", "用戶名"); formData.append("sap-password", "用戶密碼"); var request = new XMLHttpRequest(); request.open("POST", "域名b的url",false); request.send(formData); alert("response: " + request.responseText);
希望我的這個踩坑經歷對大家有點幫助。
要獲取更多Jerry的原創技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98561.html
摘要:發送到后臺的數據見下圖這種方式會以鍵值對的形式通過分隔符鏈接,以字符串給后臺,可以傳輸文件,也可以傳輸普通數據。跨域跨域問題的根本問題就是同源策略,旨在防止網站被攻擊,這里不做贅述。客戶端,以為例服務端允許跨域的請求的方法。 HTTP基礎 其實很多面試問HTTP的3次握手,4次揮手,我覺得價值不大,可以幫助你理解HTTP的原理,死背硬記的對于你開發沒有作用,而是去理解它就行。前端只關心...
摘要:實際使用時,由于向提交的長度限制在字符,超過了則被瀏覽器拒絕,因此不采用。前端發起跨域請求就是正常的請求即可。 問題背景瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、端口、協議任一不同,都是跨域 在前后端開發過程經常會遇到跨域問題。網上也都有解決方案。 寫這篇文章時,我們碰到的一個場景是:要給s系統做一個擴展,前端的html、js放在s系統里,后端需要做一個單獨的站點N.B....
摘要:今天這篇文章,我們會介紹幾種常見的方法和其中存在的問題,并提出如何基于請求攔截,快速解決跨域和代理問題的方案。因為沒有修改該請求,只是延遲發送,這樣就保持了原請求與業務服務器之間的所有鑒權等相關信息,由此解決了跨域訪問無法攜帶的問題。 近幾年,隨著 Web 開發逐漸成熟,前后端分離的架構設計越來越被眾多開發者認可,使得前端和后端可以專注各自的職能,降低溝通成本,提高開發效率。 在前后端...
摘要:這個坑就是要注意回調結束要返回成功的響應這幾天做微信支付暫時遇到的問題就這么多,只能說注意細節吧,爬過的坑記錄下來以后遇到就懂處理了。 前言 其實任何接口開發只要按照給出來的接口文檔和例子開發基本上不會有太大問題的,一些問題都是出在雜七雜八的小細節上,現在分享一下微信支付開發中自己遇到的小細節。按照文檔做完開發前配置,比如JS安全域名配置、網頁授權域名、公眾號授權目錄等等... 坑一:...
摘要:前言最近在業務代碼中深受跨域問題困擾,因此特別寫一篇博客來記錄一下自己對跨域的理解以及使用到的參考資料。內嵌式跨域通常也是允許的。而我使用時因為這個響應報文最后被認為是跨域問題,無法從中獲得的狀態碼。它代表服務器支持跨域時攜帶認證信息。 前言 最近在業務代碼中深受跨域問題困擾,因此特別寫一篇博客來記錄一下自己對跨域的理解以及使用到的參考資料。本文的項目背景基于vue+vuex+axio...
閱讀 1902·2021-11-23 09:51
閱讀 1545·2021-11-19 09:40
閱讀 3219·2021-11-11 11:01
閱讀 1118·2021-09-27 13:34
閱讀 1848·2021-09-22 15:56
閱讀 2133·2019-08-30 15:52
閱讀 1070·2019-08-30 14:13
閱讀 3483·2019-08-30 14:10