美文网首页饥人谷技术博客Vue
HTTP: 跨域真的有这么难吗

HTTP: 跨域真的有这么难吗

作者: 写代码的海怪 | 来源:发表于2019-02-08 02:08 被阅读94次

    前言

    以前写前端小项目的时候就听说过跨域这个词,什么 JSONP啊,CORS啊。感觉很高级,但是无奈项目太小没机会用上。今天就写篇博客总结一下常用的跨域操作。

    为什么要跨域

    一般来说写项目的时候都是自己给自己发请求的,如 localhost:8080 发了一个 /users 请求,本质上就是向 localhost:8080/users 发请求,这是被允许的。但是如果给支付宝发是不行的,如 post /zhifubao/sendMoney/user?money=1000,如果允许的话那每个人装一个 postman 不断发请求就可以去支付宝偷钱了(不考虑验证情况下)。所以呢跨域请求是不好的,但是在某些条件下是可以的。像大家都是兄弟公司,虽然我们域名不一样但是我们有 py 交易呀,数据都共享,你发请求给我,我也发请求给你,这就需要跨域请求了。

    JSONP

    JSONP 其实真名叫:JSON + Padding。JSON 大家都知道跟 JS 对象差不多,是一种通信格式。至于 Padding ,emmm 如果你知道这个原因就感觉很 SB。

    为什么会有 JSONP

    JSONP 本来不是用来解决跨域问题的,是用来实现发请求时不重刷页面的,这都是 Ajax 出现前的一个技术,或者说是一个替代品,只不过刚好可以用来实现跨域请求。

    前端实现

    实现思路是

    1. 定义一个 loadData 函数在全局
    function loadData(data) {
       console.log(data)
    }
    
    1. 创建一个 <script> 标签,并在 src 加上请求 url 如: /hello?callback=loadData
    2. 添加这个 <script> 标签到 document.body 上。一旦添加了浏览器马上会发一个 /hello?callback=loadData 的 GET 请求
    3. 等服务器响应后,就会执行返回的 JS 代码。一般来说这 JS 代码就是这个 loadData(data),这个 data 是服务器添加上去的,至于怎么返回 JS 代码请看服务端实现

    后端实现

    1. 首先获取查询参数里的 callback(回调函数的名字,这里就是 loadData)
    2. 然后生成要返回的数据
    3. 将数据和前端提取出来的回调函数结合,生成 JS 代码,返回到浏览器,浏览器一收到就会执行
    app.get('/hello', (req,res) => {
      let callback = req.query.callback;
      let obj = {
        userName: 'Jack',
        password: '123456'
      };
      res.writeHead(200, {"Content-Type": "text/javascript"});
      res.end(callback + '(' + JSON.stringify(obj) + ')');
    })
    

    好了,这里说下 Padding 是啥,你看到 userNamepassword 前面的空白没有,那就是 Padding,完。JSON 是因为传入回调函数的数据一般为 JSON 格式。

    CORS

    CORS 全名是 Corss Origin Resource Sharing。这种方法比较简单,因为前端发请求就好了,后端也正常返回数据。要改的是后端在返回响应时要添加一个响应头。

    app.post('/hello',(req,res) => {
      if(req.headers.origin){
        res.writeHead(200, {
          "Content-Type": "text/html; charset=UTF-8",
          "Access-Control-Allow-Origin":'http://127.0.0.1:8888'
        });
        let user= {
          userName: 'Jack',
          password: '123456'
        }
        res.end(JSON.stringify(user));
      }
    })
    

    这里解释一下:当浏览器发现发了跨域请求就会在请求头里添加 Origin: 当前域 字段。服务器此时会检测是否存在 Origin 字段,如果存在那么会在响应头里添加 Access-Control-Allow-Origin: Origin 的值 再返回 JSON 格式结果就行了。前端收到响应后,浏览器会检查 Access-Control-Allow-Origin 的值是否和当前的地址相同,如果相同才能获取到数据。

    postMessage

    这个方法主要是在前端完成的。在发送请求方只需要调用新 API 的 postMessage 函数就可以了。

    postMessage('要发送的消息', '目的地地址', '当前地址')
    

    在接受方要在 window 上监听一个 message 事件。

    function receiveMessage(event) {
      // 对发送者做检查 ,如果不是自己人就不返回
      if (event.origin !== "http://example.com:8080")
        return;
    
      // 这里可以打印发送方的消息
      console.log(event.data)
    
      // 如果是自己人,就返回数据 
      event.source.postMessage("你好,自己人",event.origin)
    }
    
    // 全局监听 `message` 事件
    window.addEventListener("message", receiveMessage, false);
    

    这种方法比较简单,但是也要做好发送方的检测。

    相关文章

      网友评论

        本文标题:HTTP: 跨域真的有这么难吗

        本文链接:https://www.haomeiwen.com/subject/dblxsqtx.html