Nodejs(四)-跨域

169 阅读5分钟

一、跨域

  • 1、什么是跨域

    • 请求所在的服务器, 与要被请求的服务器
    • 两个服务器地址
    • 上述的三个, 有一个不同, 就会触发跨域, 上边的就是我们浏览器的同源策略,只要违反了同源策略一定会触发跨域
  • 2、跨域会导致什么情况的发生

    • 请求能够正常的发送成功
    • 服务器也一定能够正常的响应成功
    • 但是浏览器会认为 当前的请求不安全, 然后将本次请求的信息拦截掉,所以最终的结果是:
      • 前端能够正常的发出去请求
      • 服务端能够正常的响应回数据
      • 但是前端不能正常的接收到数据, 因为被浏览器拦截了

二、解决跨域的三种方式

    1. jsonp
    1. cors
    1. proxy 服务器代理

1、方法一jsonp

1)server-api/index.js

const express = require("express");
const bodyParser = require("body-parser");

// 创建服务器
const server = express();

server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());

// 配置接口处理
server.get("/api/a", (req, res) => {
    // console.log('如果我打印了, 说明有人请求我了, 然后我一定会返回一个数据')
    // res.send({
    //     code: 1,
    //     msg: "请求 a 成功",
    // });

    // res.send('console.log(10086)')

    // res.send('fn(100)')
    // res.send('fn(10086)')
    // res.send('fn({code: 1, msg: "请求 a 成功"})')

    // const data = {
    //     code: 1,
    //     msg: "请求 a 成功",
    // };
    // // res.send(`fn(${data})`);    // 不允许这样传递
    // res.send(`fn(${JSON.stringify(data)})`);    // ????

    const { callback } = req.query;
    
    const data = {
        code: 1,
        msg: "请求 a 成功",
    };
    res.send(`${callback}(${JSON.stringify(data)})`);
});

server.post("/api/b", (req, res) => {
    res.send({
        code: 1,
        msg: "请求 b 成功",
    });

    // res.send('console.log(10010)')
});

// 配置端口号
server.listen(8081, () => console.log("8081 接口服务器启动成功"));

2)server-static

1.server-static/index.js

const express = require("express");

// 创建服务器
const server = express();

// 配置静态资源
server.use("/static", express.static("./client"));

// 配置端口号
server.listen(8080, () => console.log("8080 静态页面服务器启动成功"));

2.client/index.js

console.log("index.html 引入 index.js 成功");


getA()
function getA () {
    const xhr = new XMLHttpRequest()
    xhr.open('get', 'http://localhost:8081/api/a')
    xhr.send()
    xhr.onload = function () {
        console.log(xhr.responseText)
    }
}

3.client/index.html

  • 文件的名字是为了让用户知道这个文件是什么,文件的后缀(.js .css .html)是为了让一些软件认识这个文件
  • script 的 src 属性会将地址中的文件内容读取一遍,然后将文件内容当成 JS 代码执行一遍
  • 目前我们的这个写法其实就是利用了jsonp解决了跨域
    • 因为同源策略是浏览器用来限制 ajax 的,script 标签 的 src 属性, 不会收到限制, 所以可以跳出同源策略,但是当前的解决方案也不是特别完美, 因为目前的 jsonp 只能处理 get 方式的跨域, post 方式的无法解决
    <script>
        function num123(data) {
            console.log('数据: ', data)
        }
    </script>

    <script src="http://localhost:8081/api/a?callback=num123"></script>
    <!--
        当前我们已经成功实现 jsonp 处理跨域, 并且拿到了 后端返回的数据

        但是有一些问题
            函数名 一定是 fn 吗?

            我们目前没有办法确保, 函数名一定是 fn
     -->
    <!-- <script>
        function fn(data) {
            console.log('数据: ', data)
        }
    </script> -->
    <!--
        当前会像 http://localhost:8081/api/a 发送一个 get 请求
        这个接口会返回一个字符串: fn()

        然后这个标签会将这个字符串当成一个 js 代码执行一遍
     -->
    <!-- <script src="http://localhost:8081/api/a"></script> -->

    <!--
        当前页面执行的时候, 会引入一个 在线的 JS

        但是这个地址最终返回的数据不是一个 JS 文件

        而是一个字符串: console.log(10086)

        然后当前标签会把这个字符串当成一个 JS 代码执行一遍
     -->

2、方法二、cors

  • 刚才我们使用 jsonp 完成了一个 get 方式的跨域处理,但是如果我们遇到了 post 方式, 我们无法利用 jsonp 完成跨域处理
  • 利用一个 新的方式 cors 解决跨域
  • 出现跨域的流程:
      1. 前端发送请求 (发送成功)
      1. 后端反馈响应 (反馈成功)
      1. 浏览器解析后端反馈的数据 (此时发现当前的请求违反了 同源策略, 所以触发了跨域, 将后端反馈的数据浏览器拦截掉)
      1. 现在前端没有办法正常的接收到后端的数据
  • cors 解决跨域的思路
      1. 前端发送请求 (发送成功)
      1. 后端反馈响应 (反馈成功) 但是再反馈的时候告诉浏览器我们这次通讯是合法的, 请不要拦截
      1. 浏览器解析后端反馈的数据 (此时发现了当前的请求违反了 同源策略, 但是后端告诉我们当前的请求时合法的, 所以不触发跨域, 正常给前端反馈数据)
      1. 前端此时正常接收到数据了

1)server-api/index.js

image.png

3、方法三、proxy 服务器代理

proxy图示.png

1)server-static/client/index.js

    console.log("index.html 引入 index.js 成功");


getA()
function getA () {
    const xhr = new XMLHttpRequest()
    // xhr.open('get', 'http://localhost:8081/api/a')
    xhr.open('get', 'http://localhost:8080/api/mya')
    xhr.send()
    xhr.onload = function () {
        console.log(xhr.responseText)
    }
}

getB()
function getB () {
    const xhr = new XMLHttpRequest()
    xhr.open('post', 'http://localhost:8080/api/myb')
    xhr.send()
    xhr.onload = function () {
        console.log(xhr.responseText)
    }
}

2)server-static/index.js

const express = require("express");
const axios = require("axios");

// 创建服务器
const server = express();

// 配置静态资源
server.use("/static", express.static("./client"));

server.get("/api/mya", (req, res) => {
    // 当我们这个接口触发, 是我们自己的页面发了一个请求, 我们需要向 8081 这个服务器 的 /api/a 这个接口发一个请求
    // axios({
    //     method: 'GET',
    //     url: 'http://localhost:8081/api/a'
    // }).then((data) => {
    //     res.send(data.data);
    // })

    axios({
        method: "GET",
        url: "http://localhost:8081/api/a",
    }).then(({ data }) => {
        res.send(data);
    });
});

server.post("/api/myb", async (req, res) => {
    // 当我们这个接口触发, 是我们自己的页面发了一个请求, 我们需要向 8081 这个服务器 的 /api/a 这个接口发一个请求
    const { data } = await axios({
        method: "POST",
        url: "http://localhost:8081/api/b",
    });

    res.send(data);
});

// 配置端口号
server.listen(8080, () => console.log("8080 静态页面服务器启动成功"));

3)server-api/index.js

    const express = require("express");
const bodyParser = require("body-parser");

// 创建服务器
const server = express();

server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());

// 配置接口处理
server.get("/api/a", (req, res) => {
    res.send({
        code: 1,
        msg: "请求 a 成功",
    });
});

server.post("/api/b", (req, res) => {
    res.send({
        code: 1,
        msg: "请求 b 成功",
    });
});

// 配置端口号
server.listen(8081, () => console.log("8081 接口服务器启动成功"));