摘要:代碼第日前瞻中國沖擊金博爾特再戰米羽球正直播柴飚洪煒出戰男雙力爭會師決賽女排將死磕巴西郎平安排男陪練模仿對方核心執行結果用,不跨域的打開發送請求時,請求頭內部沒有當我用打開,出現跨域時。
一、同源策略
瀏覽器出于安全方面的考慮,只允許與本域下的接口交互(當前頁面得url必須和接口得url是同源的)。不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方的資源。
1、本域同協議:如都是http或者https
同域名:如都是http://jirengu.com/a 和http://jirengu.com/b
同端口:如都是80端口
舉個例子
http://jirengu.com/a/b.js 和 http://jirengu.com/index.php (同源)
不同源 http://jirengu.com/main.js 和 https://jirengu.com/a.php (協議不同) http://jirengu.com/main.js 和 http://bbs.jirengu.com/a.php (域名不同,域名必須完全相同才可以) http://jiengu.com/main.js 和 http://jirengu.com:8080/a.php (端口不同,第一個是80)2、通過ajax獲取數據,演示同源和不同源
首先打開hosts文件(window的地址是C:WindowsSystem32driversetchosts ),添加兩條host記錄
新建一個index.html文件,里面實現一個ajax獲取數據的功能
hello world
新建一個js文件,里面實現一個靜態路由功能的服務器
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getWeather": res.end(JSON.stringify({beijing: "sunny"})) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
gitbash cd到當前文件夾,通過node server.js打開服務器。
在瀏覽器輸入localhost:8080,結果成功獲取ajax數據
我把ajax請求地址改成http://a.com:8080/getWeather,結果報錯了
我把瀏覽器的地址改為a.com 把ajax的地址改為b.com或者localhost,或者127.0.0.1都會出現跨域報錯,即使他們的地址都是指向服務器。
二、JSONP(JSON with padding) 1、概念HTML 中 script 標簽可以加載其他域下的js,也就是說script的src能使用任何網站對應得文件,只要該網站愿意去提供這個東西。
這時候會向天氣接口發送請求獲取數據,獲取數據后做為 js 來執行。 但這里有個問題, 數據是 JSON 格式的數據,直接作為 JS 運行的話我如何去得到這個數據來操作呢?
這樣我們可以和后端商量一下,這樣執行:
前端提前定義好showdata這個函數。當這個請求到達后端后,后端會去解析callback這個參數獲取到字符串showData,在發送數據做如下處理:
之前后端返回數據: {"city": "hangzhou", "weather": "晴天"} 現在后端返回數據: showData({"city": "hangzhou", "weather": "晴天"}) 前端script標簽在加載數據后會把 「showData({“city”: “hangzhou”, “weather”: “晴天”})」做為 js 來執行。實際上就是調用showData這個函數,同時參數是 {“city”: “hangzhou”, “weather”: “晴天”}。
總結:JSONP是通過 script 標簽加載數據的方式去獲取數據并把數據當做 JS 代碼來執行。 提前在頁面上聲明一個函數,函數名通過接口傳參的方式傳給后臺,后臺解析到函數名后在原始數據上「包裹」這個函數名,發送給前端。換句話說,JSONP 需要對應接口的后端的配合才能實現。
2、舉個栗子2.1代碼
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getNews": var news = [ "第11日前瞻:中國沖擊4金 博爾特再戰200米羽球", "正直播柴飚/洪煒出戰 男雙力爭會師決賽", "女排將死磕巴西!郎平安排男陪練模仿對方核心" ] res.setHeader("Content-Type","text/json; charset=utf-8") if(pathObj.query.callback){ res.end(pathObj.query.callback + "(" + JSON.stringify(news) + ")") }else{ res.end(JSON.stringify(news)) } break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
打開終端,cd到對應的文件夾,輸入 node server.js ,瀏覽器打開 http://localhost:8080/index.html。
2.2執行結果
![clipboard.png](/img/bVbk
2.3分析
2.3.1
res.end(pathObj.query.callback + "(" + JSON.stringify(news) + ")")
數組和字符串相加,會把數組toString(),將數組轉換為以‘,’分隔的字符串【1,2,3】=>"1,2,3"。如果我不用json.stringify傳遞的news就是一個字符串,html里面就無法當成數組使用
2.3.2
if(pathObj.query.callback){ res.end(pathObj.query.callback + "(" + JSON.stringify(news) + ")")
以下是pathobj的輸出值,可以看到pathObj.query是一個對象,所以才可以使用pathObj.query.callback獲取對應的值
2.3.3
function appendHtml(news){ console.log(news); var html = ""; for( var i=0; i" + news[i] + ""; } console.log(html); $(".news").innerHTML = html; }
appendHtml函數收到的參數news是一個數組,和html參數是一個字符串
2.3.4
script.src = "http://127.0.0.1:8080/getNews?callback=appendHtml"; document.head.appendChild(script); document.head.removeChild(script);
把script放在document.head,是為了讓這句代碼執行發送請求。刪除removechild,是為了美觀,如果不刪除,每次點擊news都會重新產生一個script。如下圖我點擊news一次,head就會新增一個script
關于cors,我只是記錄了一個簡單的情況,經用于入門。詳細可以看這篇文章跨域資源共享 CORS 詳解
1、概念CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請求資源的方式,支持現代瀏覽器,IE支持10以上。
2、實現原理當你使用 XMLHttpRequest 發送請求時,瀏覽器發現該請求不符合同源策略,會給該請求加一個請求頭:Origin。
后臺進行一系列處理,如果確定接受請求則在返回結果中加入一個響應頭:Access-Control-Allow-Origin(允許訪問控制的域)和對應的值;
瀏覽器判斷該相應頭中是否包含 Origin 的值,如果有則瀏覽器會處理響應,我們就可以拿到響應數據,如果不包含瀏覽器直接駁回,這時我們無法拿到響應數據。
server.js
var http = require("http") var fs = require("fs") var path = require("path") var url = require("url") http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case "/getNews": var news = [ "第11日前瞻:中國沖擊4金 博爾特再戰200米羽球", "正直播柴飚/洪煒出戰 男雙力爭會師決賽", "女排將死磕巴西!郎平安排男陪練模仿對方核心" ] res.setHeader("Access-Control-Allow-Origin","http://localhost:8080") //res.setHeader("Access-Control-Allow-Origin","*") res.end(JSON.stringify(news)) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, "not found") res.end("404 Not Found
") }else{ res.end(data) } }) } }).listen(8080)
index.html
4、執行結果
用http://127.0.0.1:8080/index.html,不跨域的打開index.html發送請求時,請求頭內部沒有origin
當我用http://localhost:8080打開index.html,出現跨域時。
請求頭內部有Origin: http://localhost:8080,響應頭有Access-Control-Allow-Origin: http://localhost:8080。兩者相等,正常的獲取數據
當我使用了a.com打開index.html時(我修改了host文件讓a.com也指向127的本機服務器地址),出現了報錯。因為服務器不允許a.com的網頁使用資源
5、代碼解析res.setHeader("Access-Control-Allow-Origin","http://localhost:8080") //res.setHeader("Access-Control-Allow-Origin","*")
這個表示服務器添加允許控制的域對應的地址,*表示允許所有接口用服務器的資源
四、降域 1、iframe和網頁不同源網頁的內聯iframe和網頁不同源,我們不能通過js操作該iframe.比如我們在自己的網站上嵌套一個淘寶的frame,等用戶先登陸了淘寶,然后登陸我們的網頁的時候,處于frame的淘寶也是登陸狀態,如果我能用js去操作這個用戶的淘寶,那我就可以做很多壞事了。
2、舉個例子
使用降域實現跨域
首先修改host文件,把a.com和b.com指向127.0.0.1,打開http-server。
用a.com網址打開a.html,其中b.jrg.com的iframe的地址是b.com,和網頁不同源的。可以看到該frame可以正確加載,但我們不能用js操作它
用b.com地址打開a.html,其中b.jrg.com的iframe的地址是b.com,和網頁同源。我們就可以用js去操作該iframe。
如果當前頁面和iframe域名后面部分一致都是jrg.com,我們可以使用document.domain = "jrg.com"降域的方式來實現跨域
五、postMessage通過postMessage實現不同主域下frame的操作
window.frames[0].postMessage(this.value,"*");//* ,表示任何域下都可接受請求
window.parent.postMessage(this.value, "*");
Document
Document 使用postMessage實現跨域
打開http-server,查看結果
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99782.html
摘要:關于,強烈推薦閱讀跨域資源共享詳解阮一峰另外,這里也整理了一個實現原理圖簡化版如何判斷是否是簡單請求瀏覽器將請求分成兩類簡單請求和非簡單請求。 前言 從剛接觸前端開發起,跨域這個詞就一直以很高的頻率在身邊重復出現,一直到現在,已經調試過N個跨域相關的問題了,16年時也整理過一篇相關文章,但是感覺還是差了點什么,于是現在重新梳理了一下。 個人見識有限,如有差錯,請多多見諒,歡迎提出iss...
摘要:同源策略所謂同源是指協議,域名,端口均相同。同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源。需注意的是由于同源策略的限制,所讀取的為跨域請求接口所在域的,而非當前頁。 一、什么是跨域 1.URL解析 URL (Uniform Resource Locator )統一資源定位符(URL)是用于完整地描述Internet上網頁和其他資源的地址的...
摘要:學習建議在學習其中一種跨域方法的時候,建議邊運行項目里的,邊在網上搜索博客文章學習這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學習跨域需要配置本地服務器,可能會比較麻煩,所以自己根據網上的博客寫了大多數跨域的簡單demo,可以自己在本地運行,而且不用配置服務器。自己對于跨域的理解剛開始...
摘要:學習建議在學習其中一種跨域方法的時候,建議邊運行項目里的,邊在網上搜索博客文章學習這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學習跨域需要配置本地服務器,可能會比較麻煩,所以自己根據網上的博客寫了大多數跨域的簡單demo,可以自己在本地運行,而且不用配置服務器。自己對于跨域的理解剛開始...
摘要:學習建議在學習其中一種跨域方法的時候,建議邊運行項目里的,邊在網上搜索博客文章學習這種跨域方法,這樣有助于快速并且深入理解跨域。鑒于網上有很多文章詳細講述跨域知識,只是少了可以本地運行的,所以這里就不再贅述跨域知識。 前言 因為學習跨域需要配置本地服務器,可能會比較麻煩,所以自己根據網上的博客寫了大多數跨域的簡單demo,可以自己在本地運行,而且不用配置服務器。自己對于跨域的理解剛開始...
摘要:實現跨域的原理通過方式請求載入并執行一個文件,相當于通過的形式的導入一個外部的方法語法該函數是簡寫的函數,等價于在中,您可以通過使用形式的回調函數來加載其他網域的數據,如。將自動替換為正確的函數名,以執行回調函數。 更多詳情見http://blog.zhangbing.club/Ja... 最近在項目開發的過程中遇到一些Javascript 跨域請求的問題,今天抽空對其進行總結一下,以...
閱讀 2000·2023-04-25 16:53
閱讀 1442·2021-10-13 09:39
閱讀 606·2021-09-08 09:35
閱讀 1639·2019-08-30 13:03
閱讀 2121·2019-08-30 11:06
閱讀 1831·2019-08-30 10:59
閱讀 3188·2019-08-29 17:00
閱讀 2288·2019-08-23 17:55