跨域訪問-預請求及跨域常見問題

預請求

參考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#預請求

簡而言之,在跨域并且嘗試添加一些特殊頭及自定義頭的情況下,由于瀏覽器的安全機制,會加多一次OPTIONS預請求(詢問請求),與跨域服務器協商可以設置的頭部信息,可以允許的HTTP協議等等信息。

以如下圖一次跨域請求為例。

圖中代碼如下

 1 var settings = {
 2     type: "POST",
 3     url: 'http://www.movesun.com/cors.php?allow_method=PUT',
 4     contentType: "application/json",
 5     dataType:"json",
 6     data : {
 7         "name" : "lvyahui"
 8     },
 9     xhrFields : {
10         // withCredentials : true
11     },
12     success: function(resp) {
13         console.log(resp);
14     }
15     ,
16     headers: {
17         appkey:"87a8ea08-dbaa-11e6-b3f9-7056818a4db5",
18         "X_forwarded-for":"10.104.239.XXX"
19     }
20 };
21 $.ajax(settings);

可以看到,這段代碼在movesun.com網站下,嘗試向www.movesun.com發送跨域POST 請求,并且有自定義頭(Content-Type設置了application/json類型也是原因之一),因此瀏覽器在發送真實post請求之前,發起了一個OPTIONS請求詢問。

請求之所以可以成功,是因為后端服務器正常處理了OPTIONS請求,并且響應了正確的跨域響應頭,后端代碼cors.php如下

 1 <?php
 2 
 3 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
 4     header('Access-Control-Allow-Origin:*');
 5     header('Access-Control-Allow-Headers:appkey,X_forwarded-for,Content-Type');
 6     header('Access-Control-Allow-Methods:' . (isset($_GET['allow_method']) ? $_GET['allow_method'] : 'OPTIONS'));
 7     //header('Access-Control-Allow-Credentials:true');
 8     exit(0);
 9 }
10 
11 header('Access-Control-Allow-Origin:*');
12 
13 echo json_encode(array(
14     'code'  =>  0,
15     'msg'   =>  '',
16     'data'  =>  array()
17 ));exit(0);

可以看到服務器判斷請求類型為OPTIONS時,指定了如下幾個Http響應頭

1、Access-Control-Allow-Origin ?: 跨域服務器允許的來源地址(跟請求的Origin進行匹配),可以是*或者某個確切的地址,不允許多個地址。當然后臺代碼可以動態判斷來源地址進行動態設置,這主要是因為有時需要允許任意來源訪問,并且要攜帶Cookie,此時需要明確指定地址(原因在文后常見問題中說明),下面這段PHP代碼和Java代碼(注意Java代碼中Cookie沒有取端口,因為Cookie端口不同也算同域,可以訪問到)就是取來源地址并響應

 1 if (isset($_SERVER['HTTP_REFERER'])) {
 2     $urls = parse_url($_SERVER['HTTP_REFERER']);
 3     $url = $urls['scheme'] . '://' . $urls['host'];
 4     if (isset($urls['port'])) {
 5         $url .= ':' . $urls['port'];
 6     }
 7 } else {
 8     $url = '*';
 9 }
10 
11 header("Access-Control-Allow-Origin: " . $url);
 1 public void filter(ContainerRequestContext requestContext) throws IOException {
 2     String origin = requestContext.getHeaderString("Origin");
 3     if(origin != null && !origin.trim().equals("")
 4             // postMan 請求的protocol 是 chrome-extension://
 5             && origin.startsWith("http://")){
 6         URL url  = new URL(origin);
 7         String strUrl = url.getProtocol() + "://" + url.getHost();
 8         if(url.getPort() > 0){
 9             strUrl += ":" + url.getPort();
10         }
11         originUrl = strUrl;
12         if(!cookieDomainAuto
13                 && (sysConfig.getCookieDomain() == null || sysConfig.getCookieDomain().equals(""))){
14             cookieDomainAuto = true;
15         }
16         if(cookieDomainAuto){
17             // 動態判斷 cookie domain
18             if(url.getHost().matches(PATTERN_IP)){
19                 // IP
20                 sysConfig.setCookieDomain(url.getHost());
21             } else {
22                 int start = url.getHost().lastIndexOf('.',url.getHost().lastIndexOf('.') - 1);
23                 String domain;
24                 if(start > 0){
25                     domain = url.getHost().substring(start + 1);
26                 }else{
27                     domain = url.getHost();
28                 }
29                 // domain
30                 sysConfig.setCookieDomain(domain);
31             }
32         }
33     }
34 }
Java動態設置Allow-Origin與Cookie Domain

2、Access-Control-Allow-Methods:跨域服務器允許的請求方法。經測試發現,不論Access-Control-Allow-Methods設置為簡單請求還是復雜請求類型,所有的簡單的請求(GET,HEAD,POST)也是可以正常請求的。

3、Access-Control-Allow-Headers:跨域服務器允許客戶端添加或自定義哪些http 頭。

下面是這兩次請求的報文

OPTIONS請求報文

 1 OPTIONS http://www.movesun.com/cors.php HTTP/1.1
 2 Host: www.movesun.com
 3 Proxy-Connection: keep-alive
 4 Pragma: no-cache
 5 Cache-Control: no-cache
 6 Access-Control-Request-Method: POST
 7 Origin: http://movesun.com
 8 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36
 9 Access-Control-Request-Headers: appkey, content-type, x_forwarded-for
10 Accept: */*
11 Referer: http://movesun.com/
12 Accept-Encoding: gzip, deflate, sdch
13 Accept-Language: zh-CN,zh;q=0.8
14 
15 
16 HTTP/1.1 200 OK
17 Date: Fri, 10 Mar 2017 05:48:07 GMT
18 Server: Apache
19 Access-Control-Allow-Origin: *
20 Access-Control-Allow-Headers: appkey,X_forwarded-for,Content-Type
21 Access-Control-Allow-Methods: POST
22 Vary: User-Agent,Accept-Encoding
23 Content-Encoding: gzip
24 Content-Length: 20
25 Content-Type: text/html
26 X-Cache: MISS from SK-SQUIDDEV-11
27 X-Cache-Lookup: MISS from SK-SQUIDDEV-11:8080

POST請求報文

 1 POST http://www.movesun.com/cors.php HTTP/1.1
 2 Host: www.movesun.com
 3 Proxy-Connection: keep-alive
 4 Content-Length: 12
 5 Pragma: no-cache
 6 Cache-Control: no-cache
 7 Origin: http://movesun.com
 8 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36
 9 Content-Type: application/json
10 Accept: application/json, text/javascript, */*; q=0.01
11 X_forwarded-for: 10.104.239.194
12 appkey: 87a8ea08-dbaa-11e6-b3f9-7056818a4db5
13 Referer: http://movesun.com/
14 Accept-Encoding: gzip, deflate
15 Accept-Language: zh-CN,zh;q=0.8
16 name=lvyahui

從報文中可以看出,OPTIONS請求后臺可以拿到URL中的GET參數,也就是說,如果真實請求是GET請求,則后端在處理來詢問的OPTIONS請求時,就可以獲取到所有查詢參數了。如mozilla官網所寫,筆者調試發現,一些跨域請求,即便拋出了錯誤的情況下,請求也真的到了后臺服務器,只是響應被瀏覽器攔截了。

另外,有時不想在后臺代碼中處理OPTIONS請求,則可以在nginx server節點下做如下配置,表示攔截處理所有OPTIONS請求。

 1 location ^~ / {
 2     if ($request_method = OPTIONS ) {
 3         add_header Content-Length 0;
 4         add_header Content-Type text/plain;
 5         add_header 'Access-Control-Allow-Origin' '*';
 6         add_header 'Access-Control-Allow-Methods' '*';
 7         add_header 'Access-Control-Allow-Headers' 'appkey,X_forwarded-for,Content-Type';
 8         return 200;
 9     }
10 }

?

常見跨域問題

下面是一些跨域下常見的一些問題

  • 添加了跨域服務器不允許的自定義頭會拋出?XMLHttpRequest cannot load http://www.movesun.com/cors.php. Request header field custom_heaer is not allowed by Access-Control-Allow-Headers in preflight response.
  • 當未設置允許某種復雜請求時,使用復雜請求就會拋出如下錯誤,表示真實請求使用了服務器不允許的方法。在只允許POST的情況下,GET請求是可以被發送的,HEAD也可以成功,僅僅允許GET的情況下,POST也是可以發送成功的,HEAD也可以成功 。簡單請求都可以成功,等等,其實經測試發現,不論Access-Control-Allow-Methods設置為簡單請求還是復雜請求類型,所有的簡單的請求(GET,HEAD,POST)也是可以正常請求的。XMLHttpRequest cannot load http://www.movesun.com/cors.php. Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
  • 預處理請求沒有沒正常處理,這種是詢問請求響應了非200狀態碼,會拋出 XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Response for preflight has invalid HTTP status code 405 。如  
  • 1 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
    2     header("HTTP/1.1 405 Method Not Allowed");
    3     exit(-1);
    4 }

    ?

  • 錯誤是來源地址不是服務器所允許的來源地址。如下,此時服務器響應 Access-Control-Allow-Origin:http://www.movesun.com,表示跨域服務器允許在Origin:http://www.movesun.com 的機器上訪問,而用戶試圖在http://movesun.com跨域請求目的服務器http://movesun.qq.com/cors.php?allow_method=PUT:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://www.movesun.com' that is not equal to the supplied origin. Origin 'http://movesun.com' is therefore not allowed access.
  • 前端設置了攜帶簽名標志,但是跨域服務器不允許攜帶,沒有設置 Access-Control-Allow-Credentials:true 。如:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://movesun.com' is therefore not allowed access.
  • 前端嘗試在真實請求中攜帶簽名Cookie,跨域服務器允許攜帶Cookie,但是服務器允許所有來源地址,會報這個錯誤,在跨域攜帶cookie時,必須明確指定來源地址,比如?Access-Control-Allow-Origin:http://movesun.com。例如:XMLHttpRequest cannot load http://movesun.qq.com/cors.php?allow_method=PUT. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://movesun.com' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
并且 跨域攜帶Cookie時,跨域服務器處理詢問請求(OPTIONS)和真實請求,都必須響應明確的來源地址和允許攜帶cookie的標志。否則會報上面兩種錯誤。當然很顯然的兩次響應的Allow-Origin都是一致的。如下
 1 if('OPTIONS' ===  $_SERVER['REQUEST_METHOD']){
 2     header('Access-Control-Allow-Origin:http://movesun.com');
 3     header('Access-Control-Allow-Headers:appkey,X_forwarded-for,Content-Type');
 4     header('Access-Control-Allow-Methods:' . (isset($_GET['allow_method']) ? $_GET['allow_method'] : 'OPTIONS'));
 5     header('Access-Control-Allow-Credentials:true');
 6     exit(0);
 7 }
 8 header('Access-Control-Allow-Origin:http://movesun.com');
 9 header('Access-Control-Allow-Credentials:true');
10 echo json_encode(array(
11     'code'  =>  0,
12     'msg'   =>  '',
13     'data'  =>  array()
14 ));exit(0);

?

注意:文中的測試接口 在?http://movesun.com/cors.php ?或者?http://www.movesun.com/cors.php,感興趣的讀者可以用這個接口測試。

轉載于:https://www.cnblogs.com/lvyahui/p/6530990.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371356.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql查詢優化之一:mysql查詢優化常用方式

一、為什么查詢速度會慢&#xff1f; 一個查詢的生命周期大致可以按照順序來看&#xff1a;從客戶端&#xff0c;到服務器&#xff0c;然后在服務器上進行解析&#xff0c;生成執行計劃&#xff0c;執行&#xff0c;并返回結果給客戶端。其中在“執行”階段包含了大量為了檢索…

修復Sonar中常見的Java安全代碼沖突

本文旨在向您展示如何快速修復最常見的Java安全代碼沖突。 它假定您熟悉代碼規則和違規的概念以及Sonar如何對其進行報告。 但是&#xff0c;如果您以前從未聽說過這些術語&#xff0c;則可以閱讀Sonar Concepts或即將出版的有關Sonar的書 &#xff0c;以獲取更詳細的解釋。 為…

理解ThreadLocal

ThreadLocal:線程本地存儲&#xff0c;為每個線程都創建了變量的副本&#xff0c;線程在訪問變量時&#xff0c;可以直接訪問自己內部的副本變量。 理解幾個概念&#xff1a; 在java中ThreadLocal是一個類。 ThreadMap是一個類&#xff0c; Thread類是線程類。 ThreadLocal…

抖音右上角一個小黃點是什么_抖音官方入駐視頻號,釋放了一個什么樣的信號?...

專注視頻號觀察第 328 篇這幾天&#xff0c;視頻號生態新入駐了一個企業號&#xff0c;在圈里引起不少的轟動&#xff0c;因為這個號的名字叫做———抖音。這件事在圈里引發不少的轟動&#xff0c;很多人驚嘆&#xff1a;“連抖音都來開視頻號了&#xff0c;你還在等什么&…

資源包技巧和最佳實踐

今天是資源捆綁日。 通常&#xff0c;這是Java中最著名的國際化機制&#xff08;i18n&#xff09;。 使用它應該很容易。 但是&#xff0c;在弄臟手時會出現許多小問題。 如果您有相同的想法&#xff0c;則此文章適合您。 基本 java.util.ResourceBundle定義了用于訪問Java中翻…

springMvc-文件上傳

趕時間&#xff0c;又在寫垃圾博客&#xff0c;在心里給自己一耳巴 1.單文件上傳 2.多文件上傳 代碼&#xff1a; 頁面&#xff1a; <!DOCTYPE html><html><head><meta charset"UTF-8"><title>Insert title here</title></he…

c cuda 指定gpu_GPU并行編程:熟練使用CUDA C語言

【IT168 專稿】一個大任務通常可能被分解成許多可以一起處理的小任務&#xff0c;以便創建一個解決方案&#xff0c;這和粉刷房子的道理是一樣的&#xff0c;在粉刷之前&#xff0c;假設你需要買5公升油漆和5把刷子&#xff0c;你可以自己一個人干完采購和粉刷的活&#xff0c;…

js中使用0 “” null undefined {}需要注意

注意&#xff1a;在js中0為空&#xff08;false&#xff09; &#xff0c;代表空的還有“”&#xff0c;null &#xff0c;undefined&#xff1b; 如果做判斷if(&#xff01;上面的四種值)&#xff1b;返回均為false console.log(!null);// true console.log(!0);//true consol…

PhpStorm 10.0.3破解版下載

漢化破解版軟件下載&#xff1a; http://pan.baidu.com/s/1geNO24r 密碼: d5ci 這個漢化破解軟件解決了大綱視圖里空白的問題。 先安裝騰訊電腦管家&#xff0c;然后安裝這個軟件&#xff0c;安裝到最后提示有個文件有病毒已刪除&#xff0c;點確定后正常使用。轉載于:https://…

Jenkins:部署JEE工件

隨著持續集成和持續交付的出現 &#xff0c;我們的構建被分為不同的步驟&#xff0c;以創建部署管道。 這些步驟中的一些步驟可以是例如編譯和運行快速測試&#xff0c;運行慢速測試&#xff0c;運行自動驗收測試或發布應用程序等。 部署流程的最后一步意味著將我們的產品&…

seafile 部署_Seafile開啟webdav及讀寫性能測試

為什么要在seafile搞webdavSeafile 一直是一款可靠的文件同步web應用&#xff0c;經過個人測試&#xff0c;同一臺機器上&#xff0c;seafile在傳輸文件時的速度比nextcloud要快&#xff08;可能也與php的設置有關系&#xff09;&#xff0c;這是seafile的優勢。但是&#xff0…

Python--校園網爬蟲記

查成績&#xff0c;算分數&#xff0c;每年的綜合測評都是個固定的過程&#xff0c;作為軟件開發者&#xff0c;這些過程當然可以交給代碼去做&#xff0c;通過腳本進行網絡請求獲取數據&#xff0c;然后直接進行計算得到基礎分直接填表就好了&#xff0c;查成績再手動計算既容…

Spring–添加SpringMVC –第1部分

歡迎來到本教程的第四部分。 在這一部分中&#xff0c;我們將使用Spring MVC編寫控制器和視圖&#xff0c;并考慮我們的REST模型。 我們必須做的第一件事&#xff0c;就是根據目前的情況制作一個Web應用程序。 我們將web / WEB-INF文件夾添加到我們的項目根目錄。 在WEB-INF內創…

[Linux] 權限與指令間的關系

我們知道權限對于使用者帳號來說是非常重要的&#xff0c;因為他可以限制使用者能不能讀取/創建/刪除/修改文件或目錄&#xff01; 在這一章我們介紹了很多文件系統的管理指令&#xff0c;第五章則介紹了很多文件權限的意義。在這個小節當中&#xff0c; 我們就將這兩者結合起來…

access month函數用法_學會了這7個EXCEL日期函數技巧,老板再讓你加班,你找我!...

日期函數&#xff0c;常用年月日&#xff0c;時分秒&#xff0c;星期&#xff0c;季度&#xff0c;求差值等&#xff0c;學會以下幾個函數&#xff0c;老板再讓你加班&#xff0c;你找我&#xff01;1、記錄當前時間(不隨系統時間變化)NOW()函數與數據有效性結合&#xff0c;記…

css樣式表的選擇器與分類

css 樣式表的作用&#xff1a; 主要用于結構,樣式與行為,CSS主要的作用就是美化網頁的一個語言,它的特點: 1.結構與樣式分離的方式,便于后期維護與改版; 2.樣式定義精確到像素的級別; css樣式表的結構&#xff1a;CSS 稱為層疊樣式表 用于給網頁設置各種樣式 css樣式的語法由3部…

Spring 3.1緩存和@Cacheable

緩存在軟件領域已經存在很長時間了。 它們是那些真正有用的東西之一&#xff0c;一旦您開始使用它們&#xff0c;您會想知道如果沒有它們&#xff0c;您是如何相處的&#xff0c;所以似乎讓Spring的家伙們只是在版本中向Spring核心添加緩存實現有點奇怪。 3.1。 我猜想以前沒有…

pytorchyolov4訓練_使用pytorch-yolov5 訓練自己的數據集-2020.6.15

make yolov5 pytorch train datasets訓練所需環境 python3.5, pytorch1.3, torchvision 0.4.1 , tensorboard 1.14.0 , tensorflow-gpu1.14.0本例制作yolov5數據集 并進行數據訓練從VOC數據集轉為訓練所需的coco數據集代碼有待改進包含文件夾voc2coco/(Annotations/ JPEGImages…

meta 的作用 搜集

Meta標簽中的format-detection屬性及含義 format-detection翻譯成中文的意思是“格式檢測”&#xff0c;顧名思義&#xff0c;它是用來檢測html里的一些格式的&#xff0c;那關于meta的format-detection屬性主要是有以下幾個設置&#xff1a;<meta name"format-detecti…

Web服務安全性和SOA路線圖的人為維度

在大多數非平凡的SOA環境中&#xff0c;很難跟蹤系統之間不斷發展的集成&#xff0c;除非有明確的發布和查找適當信息的方法。 概述IT環境&#xff0c;定義當前或將要連接的內容&#xff0c;是維護環境的先決條件。 缺少這種情況通常會導致“面向意大利面條的環境”的感覺&…