搜尋
首頁後端開發php教程最全ajax跨域解決方案

最全ajax跨域解決方案

Dec 18, 2017 pm 03:32 PM
ajax解決方案

本文將和大家分享最全ajax跨域解決方案,從剛接觸前端開發起,<span style="font-size: 14px;">跨域</span>##這個詞就一直以很高的頻率在身邊重複出現,一直到現在,已經調試過N個跨域相關的問題了,16年時也整理過一篇相關文章,但是感覺還是差了點什麼,於是現在重新梳理了一下。

主題

關於跨域,有N種類型,本文只專注於ajax請求跨域<span style="font-size: 14px;"></span>(,ajax跨域只是屬於瀏覽器"同源策略"中的一部分,其它的還有Cookie跨域iframe跨域,LocalStorage跨域等這裡不做介紹),內容大概如下:

  • 什麼是ajax跨域

    • ##原理

    • 表現(整理了一些遇到的問題以及解決方案)

  • 如何解決ajax跨域

    • JSONP方式

    • CORS方式

    • 代理程式請求方式

  • #如何分析ajax跨域

    • http抓包的分析

    • #一些範例

#什麼是ajax跨域

ajax跨域的原理

ajax出現請求跨域錯誤問題,主要原因就是因為瀏覽器的「同源策略」,可以參考

#瀏覽器同源政策及其規避方法(阮一峰)

#CORS請求原理

CORS是一個W3C標準,全名為"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨來源伺服器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

基本上目前所有的瀏覽器都實現了CORS標準,其實目前幾乎所有的瀏覽器ajax請求都是基於CORS機制的,只不過可能平時前端開發人員並不關心而已(所以說其實現在CORS解決方案主要是考慮後台該如何實現的問題)。

關於CORS,強烈建議閱讀 

跨域資源共享CORS 詳解(阮一峰)

另外,這裡也整理了一個實作原理圖(簡化版):

最全ajax跨域解決方案

#如何判斷是否為簡單請求?

瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。只要同時滿足以下兩大條件,就屬於簡單請求。

  • 請求方法是以下三種方法之一:HEAD,GET,POST

  • HTTP的頭資訊不超出以下幾種欄位:

    • #Accept

    • Accept-Language

    • Content-Language

    • Last-Event-ID

    • Content-Type(只限於三個值application/x-www-form-urlencoded、     multipart/form-data、text/plain)

凡是不同時滿足上面兩個條件,就屬於非簡單請求。

ajax跨域的表現

說實話,當初整理過一篇文章,然後作為了一個解決方案,但是後來發現仍然有很多人還是不會。無奈只能耗時又耗力的調試。然而就算是我來分析,也只會根據對應的表現來判斷是否為跨域,因此這一點是很重要的。

ajax請求時,如果存在跨域現象,並且沒有進行解決,會有如下表現:(注意,是ajax請求,請不要說為什麼http請求可以,而ajax不行,因為ajax是伴隨著跨域的,所以只是http請求ok是不行的)

注意:具體的後端跨域設定請看題綱位置。

第一種現象:<span style="font-size: 14px;">No 'Access-Control-Allow-Origin' header is present on the requested resource</span>#,並且<span style="font-size: 14px;">The response had HTTP status code 404</span>

最全ajax跨域解決方案

#造成這種情況的原因如下:
  • 本次ajax請求是「非簡單請求」,所以請求前會發送一次預檢請求(OPTIONS)
  • 伺服器端後台介面沒有允許OPTIONS請求,導致無法找到對應介面位址

解決方案: 後端允許options請求

第二種現象:<span style="font-size: 14px;"></span>No 'Access-Control-Allow-Origin' header is present on the requested resource,並且<span style="font-size: 14px;"></span>##The response had HTTP status code 405

最全ajax跨域解決方案

這種現象和第一種有區別,這種情況下,後台方法允許OPTIONS請求,但是一些設定檔中(如<span style="font-size: 14px;"></span>安全設定 ),阻止了OPTIONS請求,才會導致這個現象

#解決方案: 後端關閉對應的安全配置

第三種現象:<span style="font-size: 14px;"></span>No 'Access-Control-Allow-Origin' header is present on the requested resource,並且<span style="font-size: 14px;"> </span>status 200

最全ajax跨域解決方案

#這種現象和第一種和第二種有區別,這種情況下,伺服器端後台允許OPTIONS請求,並且介面也允許OPTIONS請求,但是頭部匹配時出現不匹配現象

例如origin頭部檢查不符,比如少了一些頭部的支援(如常見的X-Requested-With頭),然後服務端就會將response回傳給前端,前端偵測到這個後就觸發XHR.onerror,導致前端控制台報錯

#解決方案: 後端增加對應的頭部支援

第四個現象:<span style="font-size: 14px;"></span>heade contains multiple values '* ,*'

最全ajax跨域解決方案

最全ajax跨域解決方案

#表現現象是,後台回應的http頭部訊息有兩個<span style="font-size: 14px;"></span>Access-Control-Allow-Origin:*

##說實話,這種問題出現的主要原因就是進行跨域配置的人不了解原理,導致了重複配置,如:

  • #常見於.net後台(一般在web .config中配置了一次origin,然後程式碼中又手動加入了一次origin(例如程式碼手動設定了返回*))

  • 常見於.net後台(在IIS和專案的webconfig中同時設定Origin:*)

#解決方案(一一對應):

  • 建議刪除程式碼中手動新增的*,只用專案配置中的即可

  • #建議刪除IIS下的設定* ,只用專案配置中的即可

    #

如何解決ajax跨域

一般ajax跨域解決就是透過JSONP解決或CORS解決,如以下:(注意,現在已經幾乎不會再使用JSONP了,所以JSONP了解下即可)

JSONP方式解決跨域問題

##jsonp解決跨域問題是一個比較古老的方案(實際中不推薦使用),這裡做簡單介紹(實際專案中如果要使用JSONP,一般會使用JQ等對JSONP進行了封裝的類別庫來進行ajax請求)

#實作原理

JSONP之所以能夠用來解決跨域方案,主要是因為<script> 腳本擁有跨域能力,而JSONP正是利用這一點來實現。具體原理如圖<span style="font-size: 14px;"></script>

最全ajax跨域解決方案

#JSONP的實作步驟大致如下(參考了來源中的文章)

  • 客戶端網頁網頁透過新增一個<script>元素,向伺服器請求JSON數據,這種做法不受同源政策限制<span style="font-size: 14px;"><pre class="brush:php;toolbar:false">&lt;span style=&quot;font-size: 14px;&quot;&gt;function addScriptTag(src) {&lt;br/&gt; var script = document.createElement(&amp;#39;script&amp;#39;);&lt;br/&gt; script.setAttribute(&quot;type&quot;,&quot;text/javascript&quot;);&lt;br/&gt; script.src = src;&lt;br/&gt; document.body.appendChild(script);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;window.onload = function () {&lt;br/&gt; addScriptTag(&amp;#39;http://example.com/ip?callback=foo&amp;#39;);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;function foo(data) {&lt;br/&gt; console.log(&amp;#39;response data: &amp;#39; + JSON.stringify(data));&lt;br/&gt;}; &lt;br/&gt; &lt;br/&gt;&lt;/script&gt;&lt;/p&gt; &lt;p&gt;請求時,接口地址是作為構建出的腳本標籤的src的,這樣,當腳本標籤構建出來時,最終的src是接口返回的內容&lt;span style=&quot;font-size: 14px;&quot;&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt;&lt;p&gt;服務端對應的介面在返回參數外新增函數包裹層&lt;span style=&quot;font-size: 14px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt; &lt;/ul&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;foo({&lt;br&gt;  &quot;test&quot;: &quot;testData&quot;&lt;br&gt;});                     &lt;br&gt;&lt;/span&gt;</pre> <ul class=" list-paddingleft-2"><li><p>由於<script>元素請求的腳本,直接作為程式碼執行。這時,只要瀏覽器定義了foo函數,函數就會立即呼叫。作為參數的JSON資料被視為JavaScript對象,而不是字串,因此避免了使用JSON.parse的步驟。 <span style="font-size: 14px;"></script>

注意,一般的JSONP介面和普通介面回傳資料是有差別的,所以介面如果要做JSONO相容,需要進行判斷是否有對應callback關鍵字參數,如果有則是JSONP請求,傳回JSONP資料,否則回傳普通資料

#使用注意

##基於JSONP的實現原理,所以JSONP只能是“GET”請求,不能進行較為複雜的POST和其它請求,所以遇到那種情況,就得參考下面的CORS解決跨域了(所以如今它也基本被淘汰了)

CORS解決跨域問題

#CORS的原理上文中已經介紹了,這裡主要介紹的是,實際專案中,後端應該如何配置以解決問題(因為大量專案實踐都是由後端進行解決的),這裡整理了一些常見的後端解決方案:

PHP後台配置

PHP後台得配置幾乎是所有後台中最為簡單的,遵循以下步驟即可:

  • 第一步:配置Php 後台允許跨域

    <span style="font-size: 14px;"><?php <br/>header('Access-Control-Allow-Origin: *');<br>header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');<br>//主要为跨域CORS配置的两大基本信息,Origin和headers<br></span>
  • 第二步:配置Apache web伺服器跨域(httpd.conf中)

原始程式碼

<span style="font-size: 14px;"><directory></directory><br>    AllowOverride none<br>    Require all denied<br><br></span>

改為以下程式碼

<span style="font-size: 14px;"><directory></directory><br>    Options FollowSymLinks<br>    AllowOverride none<br>    Order deny,allow<br>    Allow from all<br><br></span>

Node.js後台配置(express框架)

Node.js的後台也相對來說比較簡單就可以進行設定。只要用express如下設定:

<span style="font-size: 14px;">app.all('*', function(req, res, next) {<br>    res.header("Access-Control-Allow-Origin", "*");<br>    res.header("Access-Control-Allow-Headers", "X-Requested-With");<br>    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");<br>    res.header("X-Powered-By", ' 3.2.1')<br>        //这段仅仅为了方便返回json而已<br>    res.header("Content-Type", "application/json;charset=utf-8");<br>    if(req.method == 'OPTIONS') {<br>        //让options请求快速返回<br>        res.sendStatus(200); <br>    } else { <br>        next(); <br>    }<br>});<br></span>

JAVA後台設定

JAVA後台設定只需要遵循以下步驟即可:

  • #第一步:取得依賴jar套件

    #下載 cors-filter-1.7.jar, java-property-utils-1.9 .jar 這兩個庫檔案放到lib目錄下。 (放到對應項目的webcontent/WEB-INF/lib/下)

  • #第二步:如果專案用了Maven建置的,請新增如下依賴到pom.xml中:(非maven請忽略)

    <span style="font-size: 14px;"><dependency><br>    <groupid>com.thetransactioncompany</groupid><br>    <artifactid>cors-filter</artifactid><br>    <version>[ version ]</version><br></dependency><br></span>
其中版本應該是最新的穩定版本,CORS過濾器

  • #第三步:新增CORS設定到專案的Web.xml中( App/WEB-INF/web.xml)

    <span style="font-size: 14px;"><!-- 跨域配置-->    <br><filter><br>        <!-- The CORS filter with parameters --><br>        <filter-name>CORS</filter-name><br>        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class><br>        <br>        <!-- Note: All parameters are options, if omitted the CORS <br/>             Filter will fall back to the respective default values.<br/>          --><br>        <init-param><br>            <param-name>cors.allowGenericHttpRequests</param-name><br>            <param-value>true</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.allowOrigin</param-name><br>            <param-value>*</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.allowSubdomains</param-name><br>            <param-value>false</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.supportedMethods</param-name><br>            <param-value>GET, HEAD, POST, OPTIONS</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.supportedHeaders</param-name><br>            <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.exposedHeaders</param-name><br>            <!--这里可以添加一些自己的暴露Headers   --><br>            <param-value>X-Test-1, X-Test-2</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.supportsCredentials</param-name><br>            <param-value>true</param-value><br>        </init-param><br>        <br>        <init-param><br>            <param-name>cors.maxAge</param-name><br>            <param-value>3600</param-value><br>        </init-param><br><br>    </filter><br><br>    <filter-mapping><br>        <!-- CORS Filter mapping --><br>        <filter-name>CORS</filter-name><br>        <url-pattern>/*</url-pattern><br>    </filter-mapping><br></span>
請注意,以上設定檔請放到web.xml的前面,作為第一個filter存在(可以有多個filter的)

#

  • 第四步:可能的安全模块配置错误(注意,某些框架中-譬如公司私人框架,有安全模块的,有时候这些安全模块配置会影响跨域配置,这时候可以先尝试关闭它们)

NET后台配置

.NET后台配置可以参考如下步骤:

  • 第一步:网站配置

打开控制面板,选择管理工具,选择iis;右键单击自己的网站,选择浏览;打开网站所在目录,用记事本打开web.config文件添加下述配置信息,重启网站

最全ajax跨域解決方案

请注意,以上截图较老,如果配置仍然出问题,可以考虑增加更多的headers允许,比如:

<span style="font-size: 14px;">"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"            <br></span>
  • 第二步:其它更多配置,如果第一步进行了后,仍然有跨域问题,可能是:

    • 接口中有限制死一些请求类型(比如写死了POST等),这时候请去除限    制

    • 接口中,重复配置了<span style="font-size: 14px;">Origin:*</span>,请去除即可

    • IIS服务器中,重复配置了<span style="font-size: 14px;">Origin:*</span>,请去除即可

代理请求方式解决接口跨域问题

注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。

与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:

  • 前端ajax请求的是本地接口

  • 本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端

  • 一般用node.js即可代理

关于如何实现代理,这里就不重点描述了,方法和多,也不难,基本都是基于node.js的。

搜索关键字<span style="font-size: 14px;">node.js</span>,<span style="font-size: 14px;">代理请求</span>即可找到一大票的方案。

如何分析ajax跨域

上述已经介绍了跨域的原理以及如何解决,但实际过程中,发现仍然有很多人对照着类似的文档无法解决跨域问题,主要体现在,前端人员不知道什么时候是跨域问题造成的,什么时候不是,因此这里稍微介绍下如何分析一个请求是否跨域:

抓包请求数据

第一步当然是得知道我们的ajax请求发送了什么数据,接收了什么,做到这一步并不难,也不需要<span style="font-size: 14px;">fiddler</span>等工具,仅基于<span style="font-size: 14px;">Chrome</span>即可

  • <span style="font-size: 14px;">Chrome</span>浏览器打开对应发生ajax的页面,<span style="font-size: 14px;">F12</span>打开<span style="font-size: 14px;">Dev Tools</span>

  • 发送ajax请求

  • 右侧面板-><span style="font-size: 14px;">NetWork</span>-><span style="font-size: 14px;">XHR</span>,然后找到刚才的ajax请求,点进去

示例一(正常的ajax请求)

最全ajax跨域解決方案

上述请求是一个正确的请求,为了方便,我把每一个头域的意思都表明了,我们可以清晰的看到,接口返回的响应头域中,包括了

<span style="font-size: 14px;">Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept<br>Access-Control-Allow-Methods: Get,Post,Put,OPTIONS<br>Access-Control-Allow-Origin: *<br></span>

所以浏览器接收到响应时,判断的是正确的请求,自然不会报错,成功的拿到了响应数据。

示例二(跨域错误的ajax请求)

为了方便,我们仍然拿上面的错误表现示例举例。

最全ajax跨域解決方案

这个请求中,接口Allow里面没有包括<span style="font-size: 14px;">OPTIONS</span>,所以请求出现了跨域、

最全ajax跨域解決方案
这个请求中,<span style="font-size: 14px;">Access-Control-Allow-Origin: *</span>出现了两次,导致了跨域配置没有正确配置,出现了错误。

更多跨域错误基本都是类似的,就是以上三样没有满足(Headers,Allow,Origin),这里不再一一赘述。

示例三(与跨域无关的ajax请求)

当然,也并不是所有的ajax请求错误都与跨域有关,所以请不要混淆,比如以下:

最全ajax跨域解決方案

最全ajax跨域解決方案

比如这个请求,它的跨域配置没有一点问题,它出错仅仅是因为request的<span style="font-size: 14px;">Accept</span>和response的<span style="font-size: 14px;">Content-Type</span>不匹配而已。

更多

基本上都是这样去分析一个ajax请求,通过<span style="font-size: 14px;">Chrome</span>就可以知道了发送了什么数据,收到了什么数据,然后再一一比对就知道问题何在了。

写在最后的话

跨域是一个老生常谈的话题,网上也有大量跨域的资料,并且有不少精品(比如阮一峰前辈的),但是身为一个前端人员不应该浅尝而止,故而才有了本文。

漫漫前端路,望与诸君共勉之!

相关推荐:

php处理ajax请求与ajax跨域

AJAX跨域请求的详细介绍

jquery ajax跨域解决方法(json方式)


以上是最全ajax跨域解決方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何防止會話固定攻擊?如何防止會話固定攻擊?Apr 28, 2025 am 12:25 AM

防止會話固定攻擊的有效方法包括:1.在用戶登錄後重新生成會話ID;2.使用安全的會話ID生成算法;3.實施會話超時機制;4.使用HTTPS加密會話數據,這些措施能確保應用在面對會話固定攻擊時堅不可摧。

您如何實施無會話身份驗證?您如何實施無會話身份驗證?Apr 28, 2025 am 12:24 AM

實現無會話身份驗證可以通過使用JSONWebTokens(JWT)來實現,這是一種基於令牌的認證系統,所有的必要信息都存儲在令牌中,無需服務器端會話存儲。 1)使用JWT生成和驗證令牌,2)確保使用HTTPS防止令牌被截獲,3)在客戶端安全存儲令牌,4)在服務器端驗證令牌以防篡改,5)實現令牌撤銷機制,如使用短期訪問令牌和長期刷新令牌。

PHP會議有哪些常見的安全風險?PHP會議有哪些常見的安全風險?Apr 28, 2025 am 12:24 AM

PHP會話的安全風險主要包括會話劫持、會話固定、會話預測和會話中毒。 1.會話劫持可以通過使用HTTPS和保護cookie來防範。 2.會話固定可以通過在用戶登錄前重新生成會話ID來避免。 3.會話預測需要確保會話ID的隨機性和不可預測性。 4.會話中毒可以通過對會話數據進行驗證和過濾來預防。

您如何銷毀PHP會議?您如何銷毀PHP會議?Apr 28, 2025 am 12:16 AM

銷毀PHP會話需要先啟動會話,然後清除數據並銷毀會話文件。 1.使用session_start()啟動會話。 2.用session_unset()清除會話數據。 3.最後用session_destroy()銷毀會話文件,確保數據安全和資源釋放。

如何更改PHP中的默認會話保存路徑?如何更改PHP中的默認會話保存路徑?Apr 28, 2025 am 12:12 AM

如何改變PHP的默認會話保存路徑?可以通過以下步驟實現:在PHP腳本中使用session_save_path('/var/www/sessions');session_start();設置會話保存路徑。在php.ini文件中設置session.save_path="/var/www/sessions"來全局改變會話保存路徑。使用Memcached或Redis存儲會話數據,如ini_set('session.save_handler','memcached');ini_set(

您如何修改PHP會話中存儲的數據?您如何修改PHP會話中存儲的數據?Apr 27, 2025 am 12:23 AM

tomodifyDataNaphPsession,startTheSessionWithSession_start(),然後使用$ _sessionToset,修改,orremovevariables.1)startThesession.2)setthesession.2)使用$ _session.3)setormodifysessessvariables.3)emovervariableswithunset()

舉一個在PHP會話中存儲數組的示例。舉一個在PHP會話中存儲數組的示例。Apr 27, 2025 am 12:20 AM

在PHP會話中可以存儲數組。 1.啟動會話,使用session_start()。 2.創建數組並存儲在$_SESSION中。 3.通過$_SESSION檢索數組。 4.優化會話數據以提升性能。

垃圾收集如何用於PHP會議?垃圾收集如何用於PHP會議?Apr 27, 2025 am 12:19 AM

PHP會話垃圾回收通過概率機制觸發,清理過期會話數據。 1)配置文件中設置觸發概率和會話生命週期;2)可使用cron任務優化高負載應用;3)需平衡垃圾回收頻率與性能,避免數據丟失。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境