前端跨域处理方案

2023-11-08 16:35:48 浏览数 (3)

跨域处理方案

同源:协议、域名、端口号 三者一样是同源

非同源(跨域):三者只要有一个不一样就是跨域

浏览器默认存在安全访问限制:如果从当前源向另外一个源发送数据请求,默认是不允许的。

跨域错误: 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.

跨域请求在项目中的场景和意义

  1. 开发的时候是跨域的,但是项目部署上线后是同源的(现在很少了)

<!---->

    1. 我们只需要解决开发时候的跨域问题即可;

<!---->

      1. 解决办法:修改本地的hosts文件即可【原理:构建本地DNS解析缓存】
代码语言:txt复制
开发的时候
  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,所以本质是“欺骗”浏览器... 
  1. 开发和部署的时候都是跨域的

<!---->

    1. 为了实现服务器资源的合理利用,我们一个项目都是分服务器部署的【web服务器、图片服务器。。】
    2. 需要请求第三方平台的数据
    3. ...

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腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞