前端中跨域及解決措施示例詳解
1、跨越介紹
1.1、概念
概念
:跨域是瀏覽器
的同源策略
產(chǎn)生的一個(gè)限制
同源策略
:- 瀏覽器制定的一個(gè)
安全策略
,這個(gè)安全策略
的主要目標(biāo)是:不讓我們向別人的服務(wù)器
發(fā)起請(qǐng)求 同源策略
要求:同域名
、同端口號(hào)
、同協(xié)議
,不符合同源策略的,瀏覽器為了安全會(huì)阻止這個(gè)請(qǐng)求
- 瀏覽器制定的一個(gè)
1.2、如何界定服務(wù)器是自己的還是別人的
- 查看請(qǐng)求的
"協(xié)議/端口/域名
" 這3個(gè)內(nèi)容和請(qǐng)求源
(當(dāng)前打開頁面的"協(xié)議/端口/域名")是否相同 - 如果三者有一者不同,那么就會(huì)觸發(fā)
跨域錯(cuò)誤
1.3、常見源
- 常見源1:
file:///E:/
——沒有域名/端口 => 本地磁盤的路徑 - 常見源2:
http://127.0.0.1:5500/
——協(xié)議是:http,域名是:127.0.0.1,端口是:5500 => 在服務(wù)器打開的路徑
1.4、如何解決跨域錯(cuò)誤
- 注意:如果
服務(wù)端
不想給跨域請(qǐng)求數(shù)據(jù)
,那么我們解決不了跨域問題 跨域
這件事其實(shí)主導(dǎo)者
還是在服務(wù)端
,如果服務(wù)端允許我們的跨域請(qǐng)求,那么就可以發(fā)起跨域請(qǐng)求,反之就不能發(fā)起請(qǐng)求
1.5、示例跨域錯(cuò)誤
let btn = document.querySelector("#btn"); btn.addEventListener( "click" , function(){ // 演示:向百度發(fā)起一個(gè)ajax請(qǐng)求 => 這里的演示只要是和當(dāng)前源的協(xié)議、端口、域名不一致的即可 fetch("https://www.baidu.com") // 報(bào)錯(cuò):報(bào)錯(cuò)信息中的No 'Access-Control-Allow-Origin'這段話表示ajax請(qǐng)求是違背了同源策略的,此時(shí)不可以發(fā)送ajax請(qǐng)求 })
2、解決跨域——JSONP
2.1、解釋
把原本的
ajax請(qǐng)求
——替換成:在"script"標(biāo)簽
的"src"屬性
發(fā)起請(qǐng)求
示例
:<script src="https://www.baidu.com"><script>
——向百度發(fā)起請(qǐng)求
解釋
:- 如果我們定義了一個(gè)帶有src屬性的script標(biāo)簽,那么瀏覽器就會(huì)根據(jù)script標(biāo)簽的src屬性發(fā)起請(qǐng)求
- 注意1:我們當(dāng)前發(fā)起的請(qǐng)求,它的響應(yīng)數(shù)據(jù)會(huì)被當(dāng)成js來執(zhí)行!要求響應(yīng)數(shù)據(jù)必須符合js代碼執(zhí)行標(biāo)準(zhǔn),是有意義的js代碼 => 告知服務(wù)端給我們返回的響應(yīng)數(shù)據(jù)必須是有意義的js代碼
- 注意2:我們當(dāng)前發(fā)起的請(qǐng)求,請(qǐng)求方式只能是get => 因?yàn)閟cript標(biāo)簽發(fā)出去的請(qǐng)求沒有什么危害性,也算是ajax請(qǐng)求的"閹割版"
和ajax請(qǐng)求的區(qū)別
:- 發(fā)起的請(qǐng)求響應(yīng)會(huì)被當(dāng)作js代碼立即執(zhí)行,而ajax返回的請(qǐng)求響應(yīng)是被放在對(duì)象中的一條屬性
- ajax可以任意使用請(qǐng)求方式
查看請(qǐng)求是否發(fā)送
:- 在網(wǎng)絡(luò)請(qǐng)求部分將過濾分頁調(diào)成js
- 左側(cè)的請(qǐng)求圖標(biāo)是黃色的——把百度的代碼當(dāng)成js來解釋
2.2、注意
- 當(dāng)前的
script標(biāo)簽請(qǐng)求
會(huì)在頁面打開后就立即發(fā)送 - 這會(huì)導(dǎo)致有了響應(yīng)數(shù)據(jù)后,如果沒有全局函數(shù)會(huì)報(bào)錯(cuò),所以這種請(qǐng)求一定要放在全局函數(shù)創(chuàng)建后,再進(jìn)行請(qǐng)求發(fā)起!
2.3、面試
問題
:jsonp原理回答
:動(dòng)態(tài)創(chuàng)建script標(biāo)簽,src屬性指向沒有跨域限制
2.4、示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo-1</title> </head> <body> <!-- 1、先設(shè)置好回調(diào)函數(shù) --> <script> function callback(data){ console.log(data); } </script> <!-- 2、發(fā)送jsonp請(qǐng)求并攜帶數(shù)據(jù) --> <script src="https://www.baidu.com/sugrec?prod=pc&from=pc_web&wd=你好&cb=callback"></script> </body> </html>
3、解決跨域——CORS跨域
3.1、簡(jiǎn)述概念
CORS跨域
:- CORS是在服務(wù)端返回響應(yīng)的時(shí)候,向響應(yīng)頭中添加可以跨域訪問的響應(yīng)頭信息實(shí)現(xiàn)的 => 在服務(wù)端添加響應(yīng)頭實(shí)現(xiàn)的跨域方案
- 在條件允許的情況下,盡可能的使用CORS的跨域會(huì)比較好
問題
:向目標(biāo)服務(wù)器發(fā)起請(qǐng)求:http://localhost:8889報(bào)錯(cuò)- 解釋:如果用當(dāng)前頁面(open in default browser / live server)發(fā)起請(qǐng)求就會(huì)產(chǎn)生跨域問題,因?yàn)楹湍繕?biāo)服務(wù)器的路徑不一致
- 解決:
- 注意1:要先開啟測(cè)試服務(wù)器,再通過當(dāng)前頁面向測(cè)試服務(wù)器發(fā)起請(qǐng)求 => 另外:使用CORS跨域的時(shí)候,服務(wù)端必須是我們自己寫的 (或者跟后端溝通,讓他改一下響應(yīng)頭的配置項(xiàng)),因?yàn)橐芨姆?wù)端的代碼才可以,用別人的端口實(shí)現(xiàn)CORS跨域不太可能
- 我們需要配置服務(wù)器響應(yīng)頭,才可以實(shí)現(xiàn)跨域的數(shù)據(jù)訪問
- 注意2:如果服務(wù)端啟用了CORS跨域,我們可以使用所有前端的ajax技術(shù)
3.2、示例客戶端代碼
// 1、獲取頁面元素的dom對(duì)象 let btn = document.getElementById("btn"); // 3、編寫事件處理函數(shù) async function sendRequest(){ let response = await fetch("http://localhost:8889"); let data = await response.json(); console.log( data ); // 在沒有設(shè)置響應(yīng)頭時(shí),點(diǎn)擊發(fā)送請(qǐng)求是報(bào)錯(cuò)的 } // 2、給元素添加事件 btn.addEventListener("click" , sendRequest) // 4、設(shè)置服務(wù)器響應(yīng)頭步驟——這里可以用小伙伴們自己得服務(wù)端代碼,寫入這行代碼即可 // 寫入:res.setHeader("Access-Control-Allow-Origin" , "*")即可
3.3、示例服務(wù)端代碼
let http = require("http"); let chalk = require("chalk"); let server = http.createServer( ( req , res ) => { // 注意:在這里使用響應(yīng)頭添加工具,添加CORS跨域響應(yīng)頭 // res.setHeader( 響應(yīng)頭key"Access-Control-Allow-Origin" , 響應(yīng)頭value"*" ); // 配置項(xiàng) => "Access...:允許哪一個(gè)地址去進(jìn)行跨域請(qǐng)求" // 地址信息 => "*":所有地址都行;也可以寫 http://127.0.0.1:5500/這種,但是這種完整的路徑需要攜帶協(xié)議(http/其它協(xié)議) res.setHeader("Access-Control-Allow-Origin" , "*"); // 響應(yīng)數(shù)據(jù) let data = { "message": "我已經(jīng)接受到了你的請(qǐng)求, 這是我給你的回應(yīng), 我是一個(gè) json 格式", "tips": "后端返回給前端的數(shù)據(jù)", "code": 1, } // 響應(yīng)頭設(shè)置(否則無法正常顯示中文) res.setHeader("Content-Type" , "text/html;charset=utf8"); // 將數(shù)據(jù)寫入響應(yīng)體 res.write( JSON.stringify(data) ); // 結(jié)束響應(yīng) res.end(); }) server.listen(8889 , ()=>{ const port = server.address().port const text = ` 恭喜你,服務(wù)器啟動(dòng)成功啦 ${ chalk.cyan('^_^') }! 目前正在監(jiān)聽 ${ chalk.red(port) } 端口號(hào)! 基準(zhǔn)地址: ${ chalk.red('http://localhost:' + port) } ` console.log(text) });
4、解決跨域——服務(wù)器代理跨域
4.1、簡(jiǎn)述概念
服務(wù)器代理跨域
就是在本地開啟一個(gè)服務(wù)器,代理發(fā)送我們的請(qǐng)求- 可以實(shí)現(xiàn)跨域的原因是:因?yàn)橥床呗允墙o瀏覽器設(shè)置的,對(duì)服務(wù)器不生效,所以我們的服務(wù)器代理跨域是不受同源策略限制的
4.2、示例客戶端代碼
<body> <button id="btn">向百度接口發(fā)起請(qǐng)求</button> <button id="btn2">向代理服務(wù)器發(fā)起請(qǐng)求</button> <script> // 測(cè)試是否可以直接向百度發(fā)起請(qǐng)求 => 不能,會(huì)報(bào)錯(cuò) let btn = document.getElementById("btn"); function sendRequest(){ fetch("https://www.baidu.com/sugrec") } btn.addEventListener("click" , sendRequest ) // 根據(jù)代理服務(wù)器(proxy-server.js)——測(cè)試代理請(qǐng)求 let btn2 = document.getElementById("btn2"); async function sendProxyRequest(){ // 1、此時(shí)我們的代理請(qǐng)求就是 => 給本地的代理服務(wù)器發(fā)請(qǐng)求,具體服務(wù)器怎么做那是服務(wù)器的事了 let response = await fetch("http://localhost:8890"); // 2、給我們自己配置的本地服務(wù)器發(fā)送請(qǐng)求,讓它替我們向百度發(fā)請(qǐng)求 // 3、注意:如果本地服務(wù)器沒設(shè)置cors跨域的話,一樣會(huì)報(bào)錯(cuò),所以不要忘記在proxy-server.js配置響應(yīng)頭,先實(shí)現(xiàn)能給自己的服務(wù)器發(fā)送請(qǐng)求,再讓它代替我們發(fā)請(qǐng)求 let data = await response.json(); console.log( data ); } btn2.addEventListener("click" , sendProxyRequest ) </script> </body>
4.3、示例服務(wù)端代碼
let http = require("http"); let chalk = require("chalk"); let axios = require("axios"); let server = http.createServer(async ( req , res ) => { // 代理服務(wù)器配置cors跨域 res.setHeader("Access-Control-Allow-Origin" , "*"); // 配置請(qǐng)求信息 let options = { params : { prod : "pc", from : "pc_web", wd : "hello world" , // !發(fā)起的請(qǐng)求可以不帶cb => 因?yàn)檫@是服務(wù)器端 } } // 使用axios根據(jù)路徑進(jìn)行請(qǐng)求配置: let { data } = await axios("https://www.baidu.com/sugrec" , options ) // 響應(yīng)頭設(shè)置 => 否則無法正常顯示中文 // 響應(yīng)頭設(shè)置 => 否則無法正常顯示中文 res.setHeader("Content-Type" , "text/html;charset=utf8"); // 將數(shù)據(jù)寫入響應(yīng)體 res.write( JSON.stringify(data) ); // 結(jié)束響應(yīng) res.end(); }) server.listen(8890 , ()=>{ const port = server.address().port const text = ` 恭喜你, 服務(wù)器啟動(dòng)成功啦 ${ chalk.cyan('^_^') } ! 目前正在監(jiān)聽 ${ chalk.red(port) } 端口號(hào) ! 基準(zhǔn)地址: ${ chalk.red('http://localhost:' + port) } ` console.log(text) });
4.4、服務(wù)器代理原理示例圖
總結(jié)
到此這篇關(guān)于前端中跨域及解決的文章就介紹到這了,更多相關(guān)前端跨域及解決內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js指定步長(zhǎng)實(shí)現(xiàn)單方向勻速運(yùn)動(dòng)
這篇文章主要為大家詳細(xì)介紹了js指定步長(zhǎng)實(shí)現(xiàn)單方向勻速運(yùn)動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07javascript實(shí)現(xiàn)粘貼qq截圖功能(clipboardData)
這篇文章主要介紹了javascript實(shí)現(xiàn)粘貼qq截圖功能,利用clipboardData在網(wǎng)頁中實(shí)現(xiàn)截屏粘貼的功能,感興趣的小伙伴們可以參考一下2016-05-05解決layui的使用以及針對(duì)select、radio等表單組件不顯示的問題
今天小編就為大家分享一篇解決layui的使用以及針對(duì)select、radio等表單組件不顯示的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09如何通過setTimeout理解JS運(yùn)行機(jī)制詳解
這篇文章主要給大家介紹了關(guān)于如何通過setTimeout理解JS運(yùn)行機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03基于Three.js實(shí)現(xiàn)3D玉兔效果的示例代碼
2022年中秋佳節(jié)即將來臨,中秋節(jié)是我們國(guó)家的傳統(tǒng)節(jié)日。而中秋與玉兔又往往會(huì)聯(lián)系在一起,本文將用Threejs做一只會(huì)動(dòng)的3D玉兔,感興趣的可以了解一下2022-08-08使用JavaScript實(shí)現(xiàn)貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了使用JavaScript實(shí)現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09javaScript實(shí)現(xiàn)可縮放的顯示區(qū)效果代碼
這篇文章主要介紹了javaScript實(shí)現(xiàn)可縮放的顯示區(qū)效果代碼,涉及JavaScript響應(yīng)鼠標(biāo)事件動(dòng)態(tài)操作頁面元素屬性的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10微信小程序開發(fā)之圓形菜單 仿建行圓形菜單實(shí)例
本篇文章主要介紹了微信小程序開發(fā)之圓形菜單 仿建行圓形菜單實(shí)例,具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12