最通俗易懂的跨域解释
跨域问题的由来
官方解释
1、A网站通过ajax请求访问B网站的数据(即跨域名请求数据)
2、但是ajax请求只能向自己的服务器发送请求,不能进行跨域访问
原因不在服务器,而在于浏览器存在同源政策
3、什么是同源政策?
同源政策是浏览器为了保护用户信息安全,防止恶意网站窃取数据,只允许ajax请求自己的服务
器(即ajax访问地址的协议://域名:端口号都与自身服务器相同即为同源)
有趣的理解跨域
现在小明拉着女朋友ajax的手去见小明的妈(A网站),小明现在想与刚认识的女朋友名为ajax结婚,但是小明的妈(A网站)觉得不行,才认识几天就结婚,要么人品不行,要么就是贪图她家的财产,不安全,于是就拒接了小明的女朋友(ajax),问题来了,小明有几种方案?
1、听妈的,不跟ajax结婚,抛弃她,去找其她的女朋友(jsonp)
2、找妈(A网站)的亲戚(B网站),让他来告诉小明妈,这个女朋友不错,可以结婚,妈也同意了(CORS)
3、私奔,直接偷了户口本,去民政局结婚了,绕过小明妈(服务器代理)
JSONP
抛弃ajax,找到了script
script标签为什么不受同源策影响?
script属于静态访问资源,可以这么理解,脚本的来源取决于脚本所嵌入的资源的来源,比如说访问A主机的当前HTML文件中有一个script标签,这个script标签的src属性请求了一个js脚本,因为这个脚本是由A主机的HTML文件的嵌入的script标签发起请求获取的,因此这个脚本的来源是属于A主机的。
www.cnblogs.com/liuarui/p/1…
核心
A网站的客户端代码
1、在客户端全局作用域下定义函数 fn。(此端口为3000)
<script>
function fn (data) {
console.log('客户端的fn函数被调用了')
//访问到B网站返回的数据
console.log(data);
}
</script>
2.将非同源服务器端的请求地址写在script标签的src属性中(访问服务器端口为3001的资源)
<script src="http://localhost:3001/better"></script>
B网站的服务器端代码
3.在非同源服务器端的的路由为/test的接口下
app.get('/test', (req, res) => {
// 服务器返回在A网站客户端定义的全局函数的执行传入参数
const result = 'fn({name: "张三"})';
res.send(result);
});
封装jsonp
function jsonp (options) {
// 动态创建script标签
var script = document.createElement('script');
// 拼接字符串的变量
var params = '';
for (var attr in options.data) {
params += '&' + attr + '=' + options.data[attr];
}
// 随机函数名
var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
// 它已经不是一个全局函数了
// 我们要想办法将它变成全局函数
window[fnName] = options.success;
// 为script标签添加src属性,拼接get参数
script.src = options.url + '?callback=' + fnName + params;
// 将script标签追加到页面中
document.body.appendChild(script);
// 为script标签添加onload事件
script.onload = function () {
document.body.removeChild(script);
}
}
使用jsonp获取腾讯天气数据
jsonp({
url: 'https://wis.qq.com/weather/common',
data: {
source: 'pc',
weather_type: 'forecast_1h',
province: '四川省',
city: '成都市'
},
success: function (data) {
consloe.log(data)
}
})
CORS
找亲戚(B网站)说情,小明妈(A网站)同意ajax请求。
全称为 Cross-originresource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制。
简单来说就是使用原有的ajax直接进行其他网站(B网站)数据的请求,只需要在要请求的网站(B网站)服务器设置响应头,告诉(A网站)可以访问网站的数据
1、A网站通过ajax请求端口为3001的B网站数据(A网站的客户端代码)
ajax({
type: 'get',
url: 'http://localhost:3001/cross',
success: function (data) {
console.log(data)
}
})
2、设置B网站服务器的中间件,让指定域名可以访问B网站的数据 (B网站的服务器代码)
// 拦截所有请求
app.use((req, res, next) => {
// 1.允许哪些客户端访问我
// * 代表允许所有的客户端访问我
// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
// 2.允许客户端使用哪些请求方法访问我
res.header('Access-Control-Allow-Methods', 'get,post')
// 允许客户端发送跨域请求时携带cookie信息
res.header('Access-Control-Allow-Credentials', true);
next();
});
服务器代理
私奔,跳过小明妈(A网站的限制)
1、通过访问A服务器的server接口(偷户口本)(A网站客户端)
ajax({
type: 'get',
url: 'http://localhost:3000/server',
success: function (data) {
console.log(data);
}
})
2、通过server接口请B网站的数据,并res.send响应该数据给客户端(A网站服务器端)
// 引入向其他服务器端请求数据的模块
// request("url" , (错误信息, 请求, 请求返回的数据)=>{})
const request = require('request');
app.get('/server', (req, res) => {
request('http://localhost:3001/cross', (err, response, body) => {
res.send(body);
})
});
--注意request是node的模块,需要安装引入npm insatll request -save
--有不完善的,或者错误希望各位可以在评论区提出来,一起进步,谢谢! -_-!