跨域处理方案
同源:协议、域名、端口号 三者一样是同源
非同源(跨域):三者只要有一个不一样就是跨域
浏览器默认存在安全访问限制:如果从当前源向另外一个源发送数据请求,默认是不允许的。
跨域错误: Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
跨域请求在项目中的场景和意义
- 开发的时候是跨域的,但是项目部署上线后是同源的(现在很少了)
<!---->
- 我们只需要解决开发时候的跨域问题即可;
<!---->
- 解决办法:修改本地的hosts文件即可【原理:构建本地DNS解析缓存】
开发的时候
web地址:http://127.0.0.1:5500
肖总提供的数据地址:http://www.xiaozong.com/api/...
部署的时候
web地址:http://www.xiaozong.com/index.html
数据地址:http://www.xiaozong.com/api/...
修改本地hosts文件
www.xiaozong.com:80 127.0.0.1:5500
后期在自己电脑的浏览器中访问 www.xiaozong.com ,其实最后访问的是 127.0.0.1,但是浏览器认为我们的web地址是 http://www.xiaozong.com,所以本质是“欺骗”浏览器...
- 开发和部署的时候都是跨域的
<!---->
- 为了实现服务器资源的合理利用,我们一个项目都是分服务器部署的【web服务器、图片服务器。。】
- 需要请求第三方平台的数据
- ...
JSONP跨域请求方案【局限性:只支持GET请求】
代码语言:txt复制/* fetch('/asimov/subscriptions/recommended_collections').then(response => {
return response.json();
}).then(value => {
console.log(value);
}); */
// <link>、<script>、<img>... 都不存在域的限制,直接可以获取跨域资源的{请求方式:GET}
// Object.assign(obj1,obj2):合并两个对象,让obj2中的信息替换obj1中的信息,返回的是obj1的地址「obj1对象被修改了」
const isPlainObject = function isPlainObject(obj) {
let proto, Ctor;
if (!obj || Object.prototype.toString.call(obj) !== "[object Object]") return false;
proto = Object.getPrototypeOf(obj);
if (!proto) return true;
Ctor = proto.hasOwnProperty('constructor') && proto.constructor;
return typeof Ctor === "function" && Ctor === Object;
};
const jsonp = function jsonp(config) {
// 默认配置项 & 合并配置项
let initial = {
url: '',
params: null,
jsonpCallback: 'callback',
success: () => {}
};
if (!isPlainObject(config)) config = {};
let {
url,
params,
jsonpCallback,
success
} = Object.assign({}, initial, config);
// 处理PARAMS
if (params !== null) {
// 如果传递的是对象,我们把其变为URLENCODED格式字符串
if (isPlainObject(params)) params = Qs.stringify(params);
// 把参数拼接到URL的末尾
url = `${url.includes('?')?'&':'?'}${params}`;
}
// 把一个全局函数的名字,基于jsonpCallback指定的字段,拼接到URL末尾,传递给服务器
let fnname = `jsonp${ new Date()}`;
window[fnname] = function (value) {
// value从服务获取的结果,把回调函数执行
if (typeof success === 'function') success(value);
// 清除一些没用的值
delete window[fnname];
document.body.removeChild(script);
};
url = `${url.includes('?')?'&':'?'}${jsonpCallback}=${fnname}`;
// 动态创建SCRIPT,发送数据请求
let script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
};
const jsonpPromise = function jsonpPromise(config) {
if (!isPlainObject(config)) config = {};
let fnname = `jsonp${ new Date()}`,
script;
return new Promise(resolve => {
let {
url,
params,
jsonpCallback,
} = Object.assign({
url: '',
params: null,
jsonpCallback: 'callback'
}, config);
if (params !== null) {
if (isPlainObject(params)) params = Qs.stringify(params);
url = `${url.includes('?')?'&':'?'}${params}`;
}
window[fnname] = function (value) {
delete window[fnname];
document.body.removeChild(script);
resolve(value);
};
url = `${url.includes('?')?'&':'?'}${jsonpCallback}=${fnname}`;
script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
});
};
// 使用jsonp
jsonp({
url: 'http://127.0.0.1:1001/user/list',
success(value) {
console.log(value);
}
});
jsonpPromise({
url: 'https://www.baidu.com/sugrec',
params: {
prod: 'pc',
wd: '珠峰'
},
jsonpCallback: 'cb'
}).then(value => {
console.log(value);
});
proxy跨域资源代理
CORS跨域资源共享
原理:不允许跨域是因为,当前WEB页面的“源地址 origin”向服务器发送请求的时候不被允许,所以如果想解决这个问题,只需要“服务器端”设置为允许即可
Access-Control-Allow-Origin..
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!