• 技术文章 >web前端 >js教程

    详解使用Node.js怎么处理CORS

    青灯夜游青灯夜游2020-10-28 17:42:06转载252

    视频教程推荐:node js教程

    介绍

    在本文中,我们将研究怎样用 Express 配置 CORS 以及根据需要定制 CORS 中间件。

    什么是CORS

    CORS 是“跨域资源共享”的简写。它是一种允许或限制向 Web 服务器上请求资源的机制,具体取决于进行 HTTP 请求的位置。

    这种策略用于保护特定 Web 服务器免受其他网站或域的访问。只有允许的域才能访问服务器中的文件,例如样式表、图像或脚本等。

    假设你当前使用的是 http://example.com/page1,并且你引用的是来自 http://image.com/myimage.jpg 的图片,那么除非 http://image.com 允许与 http://example.com 进行跨域共享,否则将无法获取该图像。

    每个 HTTP 请求头中都有一个名为 origin 的头。它定义了域请求的来源。可以用这个头的信息来限制引用你服务器上的资源。

    默认来自任何其他来源的请求都会受到浏览器的限制。

    例如当开发时如果用的是 React 或 Vue 这类的前端库,则前端应用将运行在 http://localhost:3000 上,同时,你的 Express 服务器可能正在其他端口上运行,例如 http://localhost:2020。这时就需要在这些服务器之间允许 CORS。

    如果你在浏览器控制台中看到下图这类的错误。问题可能出在 CORS 限制上:

    1.png

    如果我们需要提供公共 API 并希望控制对某些资源的访问和使用方式时,CORS 能够发挥很大的作用。

    另外,如果想在其他网页上使用自己的 API 或文件,也可以简单地将 CORS 配置为允许自己引用,同时把其他人拒之门外。

    用 Express 配置 CORS

    首先创建一个新的项目,并创建目录结构,然后使用默认设置运行 npm init

    $ mkdir myapp
    $ cd myapp
    $ npm init -y

    接下来安装所需的模块。我们将使用 expresscors 中间件:

    $ npm i --save express
    $ npm i --save cors

    然后,开始创建一个简单的有两个路由的 Web 程序,用来演示 CORS 的工作原理。

    首先创建一个名为 index.js 的文件,用来充当 Web 服务器,并实现几个请求处理函数:

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    
    app.get('/', (req, res) => {
        res.json({
            message: 'Hello World'
        });
    });
    
    app.get('/:name', (req, res) => {
        let name = req.params.name;
    
        res.json({
            message: `Hello ${name}`
        });
    });
    
    app.listen(2020, () => {
        console.log('server is listening on port 2020');
    });

    运行服务器:

    $ node index.js

    访问 http://localhost:2020/ 服务器应该返回 JSON 消息:

    {
      "message": "Hello World"
    }

    访问 http://localhost:2020/something 应该能够看到:

    {
      "message": "Hello something"
    }

    启用所有CORS请求

    如果想为所有的请求启用 CORS,可以在配置路由之前简单地使用 cors 中间件:

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    
    app.use(cors())
    
    ......

    如果需要,这会允许在网络上的任何位置访问所有路由。所以在本例中,每个域都可以访问两条路由。

    例如,如果我们的服务器在 http://www.example.com 上运行并提供诸如图片之类的内容,则我们允许 http://www.differentdomain.com 之类的其他域从 http://www.example.com 进行引。

    因此 http://www.differentdomain.com 上的网页可以将我们的域用作图像的来源:

    <img src="http://www.example.com/img/cat.jpg">

    为单个路由启用 CORS

    如果只需要其中某一个路由,可以在某个路由中将 cors 配置为中间件:

    app.get('/', cors(), (req, res) => {
        res.json({
            message: 'Hello World'
        });
    });

    这会允许任何域访问特定的路由。在当前的情况下,其他域都只能访问 / 路由。仅在与 API(在本例中为http://localhost:2020)的相同域中发起的请求才能访问 /:name 路由。

    如果尝试另一个来源发送请求到 / 路径将会成功,并且会收到 Hello World 作为响应:

    fetch('http://localhost:2020/')
        .then(response => response.json())
        .then(data => console.log(data))
        .catch(err => console.error(err));

    运行上面的代码,会看到来自服务器的响应已成功输出到控制台:

    {
        message: 'Hello World'
    }

    如果访问除根路径以外的其他路径,例如 http://localhost:2020/namehttp://localhost:2020/img/cat.png,则此请求将会被浏览器阻止:

    fetch('http://localhost:2020/name/janith')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));

    如果在其他 Web 应用中运行代码,应该看到以下错误:

    2.png

    用选项配置CORS

    还可以用自定义选项来配置 CORS。可以根据需要配置允许的 HTTP 方法,例如 GETPOST

    下面是通过 CORS 选项允许单个域访问的方法:

    var corsOptions = {
        origin: 'http://localhost:8080',
        optionsSuccessStatus: 200 // For legacy browser support
    }
    
    app.use(cors(corsOptions));

    如果你在源中配置域名-服务器将允许来自已配置域的CORS。因此,在我们的例子中,可以从 http://localhost:8080 访问该API,并禁止其他域使用。

    如果发送一个 GET 请求,则任何路径都应该可以访问,因为这些选项是在应用在程序级别上的。

    运行下面的代码将请求从 http://localhost:8080 发送到 http://localhost:2020

    //
    fetch('http://localhost:2020/')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));
    
    //
    fetch('http://localhost:2020/name/janith')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));

    可以看到被允许从该程序和域中获取信息。

    还可以根据需要配置允许的 HTTP 方法:

    var corsOptions = {
        origin: 'http://localhost:8080',
        optionsSuccessStatus: 200 // 对于旧版浏览器的支持
        methods: "GET, PUT"
    }
    
    app.use(cors(corsOptions));

    如果从 http://localhost:8080 发送POST请求,则浏览器将会阻止它,因为仅支持 GET 和 PUT:

    fetch('http://localhost:2020', {
      method: 'POST',
      body: JSON.stringify({name: "janith"}),
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.error(err));

    用函数配置动态 CORS 源

    如果配置不满足你的要求,也可以创建函数来定制 CORS。

    例如假设要允许 http://something.com 和 http://example.com 对 .jpg 文件进行CORS共享:

    const allowlist = ['http://something.com', 'http://example.com'];
    
        const corsOptionsDelegate = (req, callback) => {
        let corsOptions;
    
        let isDomainAllowed = whitelist.indexOf(req.header('Origin')) !== -1;
        let isExtensionAllowed = req.path.endsWith('.jpg');
    
        if (isDomainAllowed && isExtensionAllowed) {
            // 为此请求启用 CORS
            corsOptions = { origin: true }
        } else {
            // 为此请求禁用 CORS
            corsOptions = { origin: false }
        }
        callback(null, corsOptions)
    }
    
    app.use(cors(corsOptionsDelegate));

    回调函数接受两个参数,第一个是传递 null 的错误,第二个是传递 { origin: false } 的选项。第二个参数可以是用 Express 的 request 对象构造的更多选项。

    所以 http://something.comhttp://example.com 上的 Web 应用将能够按照自定义配置从服务器引用扩展名为 .jpg 的图片。

    这样可以成功引用资源文件:

    <img src="http://yourdomain.com/img/cat.jpg">

    但是下面的文件将会被阻止:

    <img src="http://yourdomain.com/img/cat.png">

    从数据源加载允许的来源列表作

    还可以用保存在数据库中的白名单列表或任何一种数据源来允许 CORS:

    var corsOptions = {
        origin: function (origin, callback) {
            // 从数据库加载允许的来源列表
            // 例如:origins = ['http://example.com', 'http//something.com']
            database.loadOrigins((error, origins) => {
                callback(error, origins);
            });
        }
    }
    
    app.use(cors(corsOptions));

    原文:https://stackabuse.com/handling-cors-with-node-js/

    作者:Janith Kasun

    更多编程相关知识,可访问:编程教学!!

    以上就是详解使用Node.js怎么处理CORS的详细内容,更多请关注php中文网其它相关文章!

    本文转载于:segmentfault,如有侵犯,请联系a@php.cn删除
    专题推荐:前端 node.js cors
    上一篇:你必须要掌握的前端状态管理器 下一篇:深入浅析JavaScript中的快速排序
    第14期线上培训班

    相关文章推荐

    • 10个面向开发人员的顶级NodeJS框架• 浅谈 Node.js 中间件的工作原理• 使用Node.js “debug”模块避免日志污染应用程序日志• node和laravel项目中预渲染vue.js应用程序• node.js和php的区别有哪些?• Node.js 中间件的工作原理

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网