日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑

發布時間:2023/12/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我通過這篇文章把今天工作中遇到的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/caimuqing/p/6733405.html

這位朋友的解決方案:

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/questions/42061727/cors-error-request-header-field-authorization-is-not-allowed-by-access-control/42061962

我一一試過,在我的場景里都不能工作。

于是我查詢了Mozilla的一篇文檔:HTTP訪問控制(CORS)

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

里面談到了,在某些情況下,瀏覽器在發起“需要預檢的請求”之前,必須首先發起一個“預檢請求(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跨域和OPTION请求的一个坑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。