谷歌通過ajax獲取本地JSON檔案,為什麼會提示跨域?
阿新 • • 發佈:2018-12-31
在本地寫了一段JSON程式碼,然後用ajax讀取後,在瀏覽器開啟,發現谷歌提示涉及到跨域問題,
但是跨域是由於協議,域名,埠中有一個不同,才會跨域,我在本地訪問自己的檔案,怎麼和跨域扯上關係了??
下面是程式碼
谷歌瀏覽器
火狐瀏覽器
1、為什麼會跨域? 要回答跨域,首先要從頭來講。瀏覽器本身存在同源策略。以下理解是我整理網上的總結。
協議,域名,埠相同,視為同一個域,一個域內的指令碼僅僅具有本域內的許可權,可以理解為本域指令碼只能讀寫本域內的資源,而無法訪問其它域的資源。這種安全限制稱為同源策略。
同源策略保證了資源的隔離。一個網站的指令碼只能訪問自己的資源,就像作業系統裡程序不能訪問另一個程序的資源一樣,如果沒有同源策略,你在網站瀏覽,跳轉其他網頁,然後這個網頁就可以跨域讀取你網站中的資訊,這樣整個Web世界就無隱私可言了。這就是同源策略的重要性,它限制了這些行為。當然,在同一個域內,客戶端指令碼可以任意讀寫同源內的資源,前提是這個資源本身是可讀可寫的。
通俗的講,瀏覽器有一個很重要的安全機制,即為同源策略:不用域的客戶端指令碼在無明確授權的情況下不能讀取對方資源,跨域也就是不同源。
回答了瀏覽器的同源策略,再回答一下跨域。
只要協議,域名,埠有一個不同,就是跨域,
ajax請求一個目標地址為非本域(協議,域名,埠任意一個不同)的web資源,就是跨域。 介紹了瀏覽器同源 策略和跨域問題,接下來,開始回答正題。為什麼會跨域? ajax請求一個目標地址為非本域(協議,域名,埠任意一個不同)的web資源,就是跨域。
2、谷歌瀏覽器JSON出現了跨域問題,火狐JSON可以看到資料。這是為什麼? 既然跨域失敗,就要找原因。這很簡單,跨域的三要素,協議,域名,埠。肯定有一個不一樣,才導致跨域問題的出現。 讀取本地JSON程式碼,火狐可以正常讀取到本地的JSON檔案, 原因是:雖然允許跨域很不安全,但是如果不跨域的話又帶來很多不便。所以火狐是允許跨域的。 那麼谷歌是怎麼回事,為什麼谷歌獲取不到,會出現跨域的問題?
這裡要提一點,訪問本地計算機中的檔案,使用的是file協議
file協議主要用於訪問本地計算機中的檔案,就如同在Windows資源管理器中開啟檔案一樣,注意它是針對本地(本機)的,簡單來說,file協議是訪問你本機的檔案資源。
這麼看來,谷歌報錯的原因已經很清楚了,控制檯可以明顯看到
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
跨源請求僅支援協議方案。 :http, data, chrome, chrome-extension, https.
說白了就是,由於安全原因瀏覽器不允許跨域訪問,安全機制認為載入本地其他檔案是跨域行為。谷歌瀏覽器會跨域失敗,是因為瀏覽器安全機制不允許,而火狐為了方便允許跨域(雖然這樣很不安全)。而且在其他瀏覽器中,出現跨域問題也是這個原因,就是瀏覽器安全機制的原因。 3、為什麼谷歌不支援跨域? 這個問題,網上搜索出來的全是怎麼解決的,沒人回答是為什麼?或者沒有直接回答,但對於我這種小白來講,繞一點彎的回答,和沒回答一樣。 這是因為瀏覽器的安全策略,即禁止ajax訪問本地的檔案,這是不安全也是不允許的,舉例的話,就相當於你訪問了一個網站,然後這個網站就可 以讀取到你本地的檔案,這種行為是不允許的。 4、怎麼解決跨域問題? 1、前端人員使用的一般是JSONP進行跨域。 2、專案中使用nginx反向代理。 3、修改谷歌瀏覽器的配置。 4、在webstrom中開啟。 這四種方法,前端人員本地最方便也是最實用的就是第一種,不建議使用第三種方法,你修改了瀏覽器的配置,難道讓使用者也修改瀏覽器的配置嗎。 第二種方法,在專案中,會部署 nginx 反向代理,這裡不做具體贅述。有需要的可以自行查詢。 第四種方法,用在angula的路由中,webstrom中自帶了一個本地伺服器。會自動為你的檔案開一個埠服務。 使用jsonp解決跨域 :(僅適用於GET請求)
實現原理:<script> 標籤是不受同源策略的限制的,它可以載入任意地方的 JavaScript 檔案,而並不要求同源。
所以 JSONP 的理念就是,我和服務端約定好一個函式名,當我請求檔案的時候,服務端返回一段 JavaScript。這段 JavaScript 呼叫了我們約定好的函式,並且將資料當做引數傳入。非常巧合的一點(其實並不是),JSON 的資料格式和 JavaScript 語言裡物件的格式正好相同。所以在我們約定的函式裡面可以直接使用這個物件。
直接上程式碼
谷歌瀏覽器
火狐瀏覽器
1、為什麼會跨域? 要回答跨域,首先要從頭來講。瀏覽器本身存在同源策略。以下理解是我整理網上的總結。
協議,域名,埠相同,視為同一個域,一個域內的指令碼僅僅具有本域內的許可權,可以理解為本域指令碼只能讀寫本域內的資源,而無法訪問其它域的資源。這種安全限制稱為同源策略。
同源策略保證了資源的隔離。一個網站的指令碼只能訪問自己的資源,就像作業系統裡程序不能訪問另一個程序的資源一樣,如果沒有同源策略,你在網站瀏覽,跳轉其他網頁,然後這個網頁就可以跨域讀取你網站中的資訊,這樣整個Web世界就無隱私可言了。這就是同源策略的重要性,它限制了這些行為。當然,在同一個域內,客戶端指令碼可以任意讀寫同源內的資源,前提是這個資源本身是可讀可寫的。
ajax請求一個目標地址為非本域(協議,域名,埠任意一個不同)的web資源,就是跨域。 介紹了瀏覽器同源 策略和跨域問題,接下來,開始回答正題。為什麼會跨域? ajax請求一個目標地址為非本域(協議,域名,埠任意一個不同)的web資源,就是跨域。
2、谷歌瀏覽器JSON出現了跨域問題,火狐JSON可以看到資料。這是為什麼? 既然跨域失敗,就要找原因。這很簡單,跨域的三要素,協議,域名,埠。肯定有一個不一樣,才導致跨域問題的出現。 讀取本地JSON程式碼,火狐可以正常讀取到本地的JSON檔案, 原因是:雖然允許跨域很不安全,但是如果不跨域的話又帶來很多不便。所以火狐是允許跨域的。 那麼谷歌是怎麼回事,為什麼谷歌獲取不到,會出現跨域的問題?
跨源請求僅支援協議方案。 :http, data, chrome, chrome-extension, https.
說白了就是,由於安全原因瀏覽器不允許跨域訪問,安全機制認為載入本地其他檔案是跨域行為。谷歌瀏覽器會跨域失敗,是因為瀏覽器安全機制不允許,而火狐為了方便允許跨域(雖然這樣很不安全)。而且在其他瀏覽器中,出現跨域問題也是這個原因,就是瀏覽器安全機制的原因。 3、為什麼谷歌不支援跨域? 這個問題,網上搜索出來的全是怎麼解決的,沒人回答是為什麼?或者沒有直接回答,但對於我這種小白來講,繞一點彎的回答,和沒回答一樣。 這是因為瀏覽器的安全策略,即禁止ajax訪問本地的檔案,這是不安全也是不允許的,舉例的話,就相當於你訪問了一個網站,然後這個網站就可 以讀取到你本地的檔案,這種行為是不允許的。 4、怎麼解決跨域問題? 1、前端人員使用的一般是JSONP進行跨域。 2、專案中使用nginx反向代理。 3、修改谷歌瀏覽器的配置。 4、在webstrom中開啟。 這四種方法,前端人員本地最方便也是最實用的就是第一種,不建議使用第三種方法,你修改了瀏覽器的配置,難道讓使用者也修改瀏覽器的配置嗎。 第二種方法,在專案中,會部署 nginx 反向代理,這裡不做具體贅述。有需要的可以自行查詢。 第四種方法,用在angula的路由中,webstrom中自帶了一個本地伺服器。會自動為你的檔案開一個埠服務。 使用jsonp解決跨域 :(僅適用於GET請求)
實現原理:<script> 標籤是不受同源策略的限制的,它可以載入任意地方的 JavaScript 檔案,而並不要求同源。
所以 JSONP 的理念就是,我和服務端約定好一個函式名,當我請求檔案的時候,服務端返回一段 JavaScript。這段 JavaScript 呼叫了我們約定好的函式,並且將資料當做引數傳入。非常巧合的一點(其實並不是),JSON 的資料格式和 JavaScript 語言裡物件的格式正好相同。所以在我們約定的函式裡面可以直接使用這個物件。
直接上程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSON檔案的呼叫</title>
<script type="text/javascript" src="jquery-1.11.2.min.js"></script>
</head>
<body>
</body>
<!--引入JS-->
<script type="text/javascript" src="BW-JSON.js"></script>
<!--jsonp中 需要注意的是
<script src="car.json?callback=train"></script>
src ? 之前為檔案地址,? 之後為回撥函式callback名稱,
回撥函式可以簡寫為 cb , 然後 回撥函式 名稱要與 JSON檔案中的名稱一致
可以在 對應的檔名中看下,如,car.json?callback=loa,car.json的 函式名為 train-->
<script src="car.json?cb=train"></script>
</html>
//JS程式碼就一個方法
function train (result){
console.log(result)
}
//JSON檔案
train({
"status": "success",
"trainSystem": [
{
"key": "BX7",
"name": "BX7",
"img": ""
},
{
"key": "BX5",
"name": "BX5",
"img": ""
},
{
"key": "BX6",
"name": "BX6",
"img": ""
}
]
})