关于前端js跨域的一些心得

本文深入探讨了前端JavaScript跨域问题的原因与解决策略,包括JSONP实现原理与配置,及通过设置Access-Control-Allow-Origin实现跨域请求。文章还介绍了XHR对象处理跨域请求的三种类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于前端js跨域的一些心得

原因

浏览器使用 XMLHttpRequest 发送请求的时候若是请求域名地址与当前域名不相同的时候,浏览器处于安全考虑会阻止请求的发送。这就是所谓的跨域问题。

解决方案

1. jsonp实现。

jsonp原理是浏览器请求资源文件的时候并不会去限制,所以可以请求到其他域的文件。下面是一个简单的实现。 jsonp.js

let connect = require("../connect");
let handleSendData = require("./ajaxData").setUrlencodedData;
let process = new connect();

// 默认参数
const defaultConfig = {
    jsonp: 'callback',
    prefix: "my_jsonp_callback_",
    data: {},
    success: function(result) {
        console.dir(result);
    },
    headers: {
        charset: "utf-8",
        type: "text/javascript"
    },
    url: "",
    fail: function() {},
    error: function(err) {
        console.dir(err);
    }
};

// 创建唯一的callback函数的编号
let uniqueNumber = 1;

// 清空操作
let clear = function(data) {
    let js = data.js;
    let req = data.req;
    js.parentNode && js.parentNode.removeChild(js);
    delete window[req.data[req.jsonp]];
};

// 发送请求前的配置
let sendProcess = {
    init: function() {
        // 初始化需要处理的部分  
        process.use(this.setSendData);
        process.use(this.setHeader);
        process.use(this.loadEvent);
        process.use(this.errorEvent);

    },
    // 设置script属性
    setHeader: function(next, data) {
        let req = data.req;
        let js = data.js;
        let headers = req.headers;
        Object.keys(headers).forEach((key) => {
            js.setAttribute(key, headers[key]);
        });

        next();
    },
    // 设置返回事件
    loadEvent: function(next, data) {
        let req = data.req;
        window[req.data[req.jsonp]] = function(cb) {
            req.success(cb);
            clear(data);
        };
        next();
    },
    // 设置失败事件
    errorEvent: function(next, data) {
        let req = data.req;
        let js = data.js;
        js.onerror = (e) => {
            req.error(e);
            clear(data);
        };
        next();
    },
    // 设置传值
    setSendData: function(next, data) {
        let req = data.req;
        // 设置返回的毁掉函数 函数名每次唯一所以不存在缓存问题
        req.data[req.jsonp] = req.prefix + (++uniqueNumber);

        handleSendData(data);
        next();
    }
};

let sendJsonp = function(data) {
    data = Object.assign({}, defaultConfig, data);
    let js = document.createElement("script");
    process.data.js = js;
    process.data.req = data;

    process.handle();
    let connectSymbol = "?";
    if (~data.url.indexOf("?")) {
        connectSymbol = "&";
    }
    js.src = `${data.url}${connectSymbol}${data.sendData}`;
    document.getElementsByTagName("head")[0].appendChild(js);
};
sendProcess.init();

module.exports = sendJsonp;
复制代码

下面是node作为服务器部分的处理jsonp请求,简单的判断参数中是否有callback有的话将其作为函数名包裹返回数据返回。 response.js

const jsonp = {
    jsonpKey: "callback",
    isJsonp: function(req) {
        if (req.body[this.jsonpKey]) {
            return true;
        }
        return false;
    },
    handleJSONPsend: function(req, responseString) {
        let callbackName = req.body[this.jsonpKey];
        return `${callbackName}(${responseString})`;
    }
};
exports = module.exports = function(req, res, next) {
    res.sendJSON = function(data) {
        let response = {
            code: 200,
            data: data
        };
        let responseString = JSON.stringify(response);
        if (jsonp.isJsonp(req)) {
            responseString = jsonp.handleJSONPsend(req, responseString);
        }
        res.send(responseString);
    };

    next();
};

复制代码

2 通过设置Access-Control-Allow-Origin

对于客户端,我们还是正常使用xhr对象发送ajax请求。
唯一需要注意的是,我们需要设置我们的xhr属性withCredentials为true,不然的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;
对于服务器端,需要在 response header中设置如下两个字段:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials:true 这样,我们就可以跨域请求接口了。
XHR对象对于HTTP跨域请求有三种:简单请求Preflighted 请求Preflighted 认证请求
简单请求不需要发送 OPTIONS 嗅探请求,但只能按发送简单的GET、HEAD或POST请求,且不能自定义HTTP Headers
Preflighted 请求认证请求,XHR会首先发送一个 OPTIONS 嗅探请求,然后XHR会根据OPTIONS请求返回的Access-Control-*等头信息判断是否有对指定站点的访问权限,并最终决定是否发送实际请求信息。所以我们在network里面查看的时候会发现请求发了两次。 下面是《图解http》中对options的解释 options : 询问支持的方法,用来查询针对请求url指定资源支持的方法。

转载于:https://juejin.im/post/5c3711cf51882525a94e1086

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值