JavaScript瀏覽器的跨域問題解決方案
為什么要跨域
同源策略
瀏覽器的同源策略:是瀏覽器的一個(gè)安全功能,不同源的網(wǎng)頁腳本在沒有明確授權(quán)的情況下,不能讀寫對方的資源,也就是會阻止一個(gè)域的javascript腳本和另外一個(gè)域的內(nèi)容進(jìn)行交互
同源
同源指的是(“協(xié)議+域名+端口”)三者相同
跨域問題
解釋:使用AJAX技術(shù)(XML HttpRequest對象),從一個(gè)網(wǎng)頁去請求另一個(gè)網(wǎng)頁的資源時(shí),違反了瀏覽器的同源策略,限制引起的安全問題。
解決跨域的思路:
- 根源上解決,不使用ajax技術(shù)
- 授權(quán)跨域資源共享
解決跨域
(列舉三個(gè)最常用的CORS、JSONP和代理服務(wù)器nginx)
CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標(biāo)準(zhǔn),屬于跨源 AJAX 請求的根本解決方法。
- 普通跨域請求只需要服務(wù)端設(shè)置 Access-Control-Allow-Origin
- 帶cookie的跨域請求前后端都需要設(shè)置
【前端設(shè)置】根據(jù)xhr.withCredentials字段判斷是否帶有cookie
1.原生ajax寫法
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端設(shè)置是否帶cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
2.jQuery ajax
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端設(shè)置是否帶cookie
},
crossDomain: true, // 會讓請求頭中包含跨域的額外信息,但不會含cookie
});
3.vue-resource
Vue.http.options.credentials = true
4.axios
axios.defaults.withCredentials = true
5.fetch()方法實(shí)現(xiàn)
<script>
fetch("http://127.0.0.1:35911", // url地址
{method: "GET"}) // 用服務(wù)器允許的方法請求
.then{ resonse => response.json{} } //
.then{ data => console.log{data.like} };
</script>
fetch方法的node.js后臺設(shè)置
cosnt express = require{'express '};
const cors = require{'cors'};
const app = express{};
app.use(
cors ({
origin:"*", // 允許所有源進(jìn)行訪問
methods:['GET','POST'] // 定義可以訪問的方法
})
);
app.get('/',{request,response} =>{
response.json(
{"name:"hello","wrold"}
);
});
app.listen(35911);【服務(wù)端設(shè)置】
服務(wù)器端對于CORS的支持,主要是通過設(shè)置Access-Control-Allow-Origin來進(jìn)行的。如果瀏覽器檢測到相應(yīng)的設(shè)置,就可以允許Ajax進(jìn)行跨域的訪問。
1.Nodejs后臺
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
var postData = '';
// 數(shù)據(jù)塊接收中
req.addListener('data', function(chunk) {
postData += chunk;
});
// 數(shù)據(jù)接收完畢
req.addListener('end', function() {
postData = qs.parse(postData);
// 跨域后臺設(shè)置
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true', // 后端允許發(fā)送Cookie
'Access-Control-Allow-Origin': 'http://www.domain1.com', // 允許訪問的域(協(xié)議+域名+端口)
/*
* 此處設(shè)置的cookie還是domain2的而非domain1,因?yàn)楹蠖艘膊荒芸缬驅(qū)慶ookie(nginx反向代理可以實(shí)現(xiàn)),
* 但只要domain2中寫入一次cookie認(rèn)證,后面的跨域接口都能從domain2中獲取cookie,從而實(shí)現(xiàn)所有的接口都能跨域訪問
*/
'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是讓js無法讀取cookie
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080...');2.PHP后臺
<?php
header("Access-Control-Allow-Origin:*");
JSONP技術(shù)原理
JSONP 是服務(wù)器與客戶端跨源通信的常用方法。最大特點(diǎn)就是簡單適用,兼容性好(兼容低版本IE),缺點(diǎn)是只支持get請求,不支持post請求。
核心思想:網(wǎng)頁通過添加一個(gè)<script>元素,向服務(wù)器請求 JSON 數(shù)據(jù),服務(wù)器收到請求后,將數(shù)據(jù)放在一個(gè)指定名字的回調(diào)函數(shù)的參數(shù)位置傳回來。
1.原生實(shí)現(xiàn)
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服務(wù)器test.com發(fā)出請求,該請求的查詢字符串有一個(gè)callback參數(shù),用來指定回調(diào)函數(shù)的名字
// 處理服務(wù)器返回回調(diào)函數(shù)的數(shù)據(jù)
<script type="text/javascript">
function dosomething(res){
// 處理獲得的數(shù)據(jù)
console.log(res.data)
}
</script>2.Query ajax
$.ajax({
// 請求域名
url:'http://10.10.0.101:8899/login',
// 請求方式
type:'GET',
// 數(shù)據(jù)類型選擇 jsonp
dataType:'jsonp',
// 回調(diào)方法名
jsonpCallback:'callback',
});
// 回調(diào)方法
function callback(response) {
console.log(response);
}3.Vue.js
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
代理服務(wù)器nginx
跨域限制是瀏覽器的同源策略導(dǎo)致的,使用 nginx 當(dāng)做服務(wù)器訪問別的服務(wù)的 HTTP 接口是不需要執(zhí)行 JS 腳本就不存在同源策略限制的,所以可以利用 Nginx 創(chuàng)建一個(gè)代理服務(wù)器,這個(gè)代理服務(wù)器的域名跟瀏覽器要訪問的域名一致,然后通過這個(gè)代理服務(wù)器修改 cookie 中的域名為要訪問的 HTTP接口的域名,通過反向代理實(shí)現(xiàn)跨域。
Nginx 的配置信息:
server {
# 代理服務(wù)器的端口
listen 88;
# 代理服務(wù)器的域名
server_name http://127.0.0.1;
location / {
# 反向代理服務(wù)器的域名+端口
proxy_pass http://127.0.0.2:89;
# 修改cookie里域名
proxy_cookie_domain http://127.0.0.2 http://127.0.0.1;
index index.html index.htm;
# 設(shè)置當(dāng)前代理服務(wù)器允許瀏覽器跨域
add_header Access-Control-Allow-Origin http://127.0.0.1;
# 設(shè)置當(dāng)前代理服務(wù)器允許瀏覽器發(fā)送 cookie
add_header Access-Control-Allow-Credentials true;
}
}
前端代碼:
var xhr = new XMLHttpRequest();
// 設(shè)置瀏覽器允許發(fā)送 cookie
xhr.withCredentials = true;
// 訪問 nginx 代理服務(wù)器
xhr.open('get', 'http://127.0.0.1:88', true);
xhr.send();
到此這篇關(guān)于JavaScript瀏覽器的跨域問題解決方案的文章就介紹到這了,更多相關(guān)JS瀏覽器跨域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript模板引擎應(yīng)用場景及實(shí)現(xiàn)原理詳解
這篇文章主要介紹了JavaScript模板引擎應(yīng)用場景及實(shí)現(xiàn)原理,結(jié)合實(shí)例形式詳細(xì)分析了javascript模版引擎的具體應(yīng)用場景、實(shí)現(xiàn)原理、相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-12-12
簡單的JS控制button顏色隨點(diǎn)擊更改的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄唵蔚腏S控制button顏色隨點(diǎn)擊更改的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
如何用JS實(shí)現(xiàn)簡單的數(shù)據(jù)監(jiān)聽
這篇文章主要介紹了如何用JS實(shí)現(xiàn)簡單的數(shù)據(jù)監(jiān)聽,對數(shù)據(jù)監(jiān)聽感興趣的同學(xué),可以參考一下2021-05-05
JavaScript連接組件實(shí)現(xiàn)打印功能
這篇文章主要為大家詳細(xì)介紹了JavaScript如何連接連接抖音打印組件實(shí)現(xiàn)打印小票功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-04-04
javascript基于牛頓迭代法實(shí)現(xiàn)求浮點(diǎn)數(shù)的平方根【遞歸原理】
這篇文章主要介紹了javascript基于牛頓迭代法實(shí)現(xiàn)求浮點(diǎn)數(shù)的平方根,簡單說明了牛頓迭代法的原理,并結(jié)合實(shí)例分析了javascript基于遞歸的數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-09-09

