创建安全Node.js GraphQL API的快速指南

创建安全Node.js GraphQL API的快速指南

本文的目标是提供关于如何创建安全的 Node.js GraphQL API 的快速指南。【视频教程推荐:node js教程 】

你可能会想到一些问题:

使用 GraphQL API 的目的是什么?什么是GraphQL API?什么是GraphQL查询?GraphQL的好处是什么?GraphQL是否优于REST?为什么我们使用Node.js?

这些问题都是有意义的,但在回答之前,我们应该深入了解当前 Web 开发的状态:

现在几乎所有的解决方案都使用了某种应用程序编程接口(API)。即使你只用社交网络(如Facebook或Instagram),仍然会用到使用API的前端。如果你感到好奇,你会发现几乎所有在线娱乐服务都在用不同类型的API,包括Netflix,Spotify和YouTube等。

你会发现几乎在每种情况下都会有一个不需要你去详细了解的API,例如你不需要知道它们是怎样构建的,并且不需要使用与他们相同的技术就能够将其集成到你自己的系统中。API允许你提供一种可以在服务器和客户端通信之间进行通用标准通信的方式,而不必依赖于特定的技术栈。

通过结构良好的API,可以拥有可靠、可维护且可扩展的API,可以为多种客户端和前端应用提供服务。

什么是 GraphQL API?

GraphQL 是一种 API 所使用的查询语言,由Facebook开发并用于其内部项目,并于2015年公开发布。它支持读取、写入和实时更新等操作。同时它也是开源的,通常会与REST和其他架构放在一起进行比较。简而言之,它基于:

GraphQL查询  —— 允许客户端进行读取和控制接收数据的方式。GraphQL 修改  —— 描述怎样在服务器上写入数据。关于怎样将数据写入系统的GraphQL约定。

虽然本文应该展示一个关于如何构建和使用GraphQL API的简单但真实的场景,但我们不会去详细介绍GraphQL。因为GraphQL团队提供了全面的文档,并在Introduction to GraphQL中列出了几个最佳实践。

什么是GraphQL查询?

如上所述,查询是客户端从API读取和操作数据的一种方式。你可以传递对象的类型,并选择要接收的字段类型。下面是一个简单的查询:

query{  users{    firstName,    lastName  }}

登录后复制

我们尝试从用户库中查询所有用户,但只接收firstName和lastName。此查询的结果将类似于:

{  "data": {    "users": [      {        "firstName": "Marcos",        "lastName": "Silva"      },      {        "firstName": "Paulo",        "lastName": "Silva"      }    ]  }}

登录后复制

客户端的使用非常简单。

使用GraphQL API的目的是什么?

创建API的目的是使自己的软件具有可以被其他外部服务集成的能力。即使你的程序被单个前端程序所使用,也可以将此前端视为外部服务,为此,当通过API为两者之间提供通信时,你能够在不同的项目中工作。

如果你在一个大型团队中工作,可以将其拆分为创建前端和后端团队,从而允许他们使用相同的技术,并使他们的工作更轻松。

在本文中,我们将重点介绍怎样构建使用GraphQL API的框架。

GraphQL比REST更好吗?

GraphQL是一种适合多种情况的方法。 REST是一种体系结构方法。如今,有大量的文章可以解释为什么一个比另一个好,或者为什么你应该只使用REST而不是GraphQL。另外你可以通过多种方式在内部使用GraphQL,并将API的端点维护为基于REST的架构。

你应该做的是了解每种方法的好处,分析自己正在创建的解决方案,评估你的团队使用解决方案的舒适程度,并评估你是否能够指导你的团队快速掌握这些技术。

本文更偏重于实用指南,而不是GraphQL和REST的主观比较。如果你想查看这两者的详细比较,我建议你查看我们的另一篇文章,为什么GraphQL是API的未来。

在今天的文章中,我们将专注于怎样用Node.js创建GraphQL API。

为什么要使用Node.js?

GraphQL有好几个不同的支持库可供使用。出于本文的目的,我们决定使用Node.js环境下的库,因为它的应用非常广泛,并且Node.js允许开发人员使用他们熟悉的前端语法进行服务器端开发。

掌握GraphQL

我们将为自己的 GraphQL API 设计一个构思的框架,在开始之前,你需要了解Node.js和Express的基础知识。这个GraphQL示例项目的源代码可以在这里找到(https://github.com/makinhs/no…)。

我们将会处理两种类型的资源:

Users ,处理基本的CRUD。Products, 我们对它的介绍会详细一点,以展示GraphQL更多的功能。

Users 包含以下字段:

idfirstnamelastnameemailpasswordpermissionLevel

Products 包含以下字段:

idnamedescriptionprice

至于编码标准,我们将在这个项目中使用TypeScript。

让我们开始编码!

首先,要确保安装了最新的Node.js版本。在本文发布时,在Nodejs.org上当前版本为10.15.3。

初始化项目

让我们创建一个名为node-graphql的新文件夹,并在终端或Git CLI控制台下使用以下命令:npm init。

配置依赖项和TypeScript

为了节约时间,在我们的Git存储库中找到以下代码去替换你的package.json应该包含的依赖项:

{  "name": "node-graphql",  "version": "1.0.0",  "description": "",  "main": "dist/index.js",  "scripts": {    "tsc": "tsc",    "start": "npm run tsc && node ./build/app.js"  },  "author": "",  "license": "ISC",  "dependencies": {    "@types/express": "^4.16.1",    "@types/express-graphql": "^0.6.2",    "@types/graphql": "^14.0.7",    "express": "^4.16.4",    "express-graphql": "^0.7.1",    "graphql": "^14.1.1",    "graphql-tools": "^4.0.4"  },  "devDependencies": {    "tslint": "^5.14.0",    "typescript": "^3.3.4000"  }}

登录后复制

更新package.json后,在终端中执行:npm install。

接着是配置我们的TypeScript模式。在根文件夹中创建一个名为tsconfig.json的文件,其中包含以下内容:

{  "compilerOptions": {    "target": "ES2016",    "module": "commonjs",    "outDir": "./build",    "strict": true,    "esModuleInterop": true  }}

登录后复制

这个配置的代码逻辑将会出现在app文件夹中。在那里我们可以创建一个app.ts文件,在里面添加以下代码用于基本测试:

console.log('Hello Graphql Node API tutorial');

登录后复制

通过前面的配置,现在我们可以运行 npm start 进行构建和测试了。在终端控制台中,你应该能够看到输出的字符串“Hello Graphql Node API tutorial”。在后台场景中,我们的配置会将 TypeScript 代码编译为纯 JavaScript,然后在build文件夹中执行构建。

现在为GraphQL API配置一个基本框架。为了开始我们的项目,将添加三个基本的导入:

ExpressExpress-graphqlGraphql-tools

把它们放在一起:

import express from 'express';import graphqlHTTP from 'express-graphql';import {makeExecutableSchema} from 'graphql-tools';

登录后复制

现在应该能够开始编码了。下一步是在Express中处理我们的程序和基本的GraphQL配置,例如:

import express from 'express';import graphqlHTTP from 'express-graphql';import {makeExecutableSchema} from 'graphql-tools';const app: express.Application = express();const port = 3000;let typeDefs: any = [`  type Query {    hello: String  }       type Mutation {    hello(message: String) : String  }`];let helloMessage: String = 'World!';let resolvers = {    Query: {        hello: () => helloMessage    },    Mutation: {        hello: (_: any, helloData: any) => {            helloMessage = helloData.message;            return helloMessage;        }    }};app.use(    '/graphql',    graphqlHTTP({        schema: makeExecutableSchema({typeDefs, resolvers}),        graphiql: true    }));app.listen(port, () => console.log(`Node Graphql API listening on port ${port}!`));

登录后复制

我们正在做的是:

为Express服务器启用端口3000。定义我们想要用作快速示例的查询和修改。定义查询和修改的工作方式。

好的,但是typeDefs和resolvers中发生了什么,它们与查询和修改的关系又是怎样的呢?

typeDefs – 我们可以从查询和修改中获得的模式的定义。Resolvers – 在这里我们定义了查询和修改的功能和行为,而不是想要的字段或参数。Queries – 我们想要从服务器读取的“获取方式”。Mutations – 我们的请求将会影响在自己的服务器上的数据。

现在让我们再次运行npm start,看看我们能得到些什么。我们希望该程序运行后产生这种效果:Graphql API 侦听3000端口。

我们现在可以试着通过访问 http://localhost:3000/graphql 查询和测试GraphQL API:

1.png

好了,现在可以编写第一个自己的查询了,先定义为“hello”。

2.png

请注意,我们在typeDefs中定义它的方式,页面可以帮助我们构建查询。

这很好,但我们怎样才能改变值呢?当然是mutation!

现在,让我们看看当我们用mutation对值进行改变时会发生什么:

3.png

现在我们可以用GraphQL Node.js API进行基本的CRUD操作了。接下来开始使用这些代码。

Products

对于Products,我们将使用名为products的模块。为了是本文不那么啰嗦,我们将用内存数据库进行演示。先定义一个模型和服务来管理Products。

我们的模型将基于以下内容:

export class Product {  private id: Number = 0;  private name: String = '';  private description: String = '';  private price: Number = 0;  constructor(productId: Number,    productName: String,    productDescription: String,    price: Number) {    this.id = productId;    this.name = productName;    this.description = productDescription;    this.price = price;  }}

登录后复制

与GraphQL通信的服务定义为:

export class ProductsService {    public products: any = [];    configTypeDefs() {        let typeDefs = `          type Product {            name: String,            description: String,            id: Int,            price: Int          } `;        typeDefs += `           extend type Query {          products: [Product]        }        `;        typeDefs += `          extend type Mutation {            product(name:String, id:Int, description: String, price: Int): Product!          }`;        return typeDefs;    }    configResolvers(resolvers: any) {        resolvers.Query.products = () => {            return this.products;        };        resolvers.Mutation.product = (_: any, product: any) => {            this.products.push(product);            return product;        };    }}

登录后复制

Users

对于users,我们将遵循与products模块相同的结构。我们将为用户提供模型和服务。该模型将定义为:

export class User {    private id: Number = 0;    private firstName: String = '';    private lastName: String = '';    private email: String = '';    private password: String = '';    private permissionLevel: Number = 1;    constructor(id: Number,                firstName: String,                lastName: String,                email: String,                password: String,                permissionLevel: Number) {        this.id = id;        this.firstName = firstName;        this.lastName = lastName;        this.email = email;        this.password = password;        this.permissionLevel = permissionLevel;    }}

登录后复制

同时,我们的服务将会是这样:

const crypto = require('crypto');export class UsersService {    public users: any = [];    configTypeDefs() {        let typeDefs = `          type User {            firstName: String,            lastName: String,            id: Int,            password: String,            permissionLevel: Int,            email: String          } `;        typeDefs += `           extend type Query {          users: [User]        }        `;        typeDefs += `          extend type Mutation {            user(firstName:String,             lastName: String,             password: String,             permissionLevel: Int,             email: String,             id:Int): User!          }`;        return typeDefs;    }    configResolvers(resolvers: any) {        resolvers.Query.users = () => {            return this.users;        };        resolvers.Mutation.user = (_: any, user: any) => {          let salt = crypto.randomBytes(16).toString('base64');          let hash = crypto.createHmac('sha512', salt).update(user.password).digest("base64");          user.password = hash;          this.users.push(user);          return user;        };    }}

登录后复制

提醒一下,源代码可以在 https://github.com/makinhs/no… 找到。

现在运行并测试我们的代码。运行npm start,将在端口3000上运行服务器。我们现在可以通过访问http://localhost:3000/graphql来测试自己的GraphQL

尝试一个mutation,将一个项目添加到我们的product列表中:

4.png

为了测试它是否有效,我们现在使用查询,但只接收id,name和price:

query{  products{    id,    name,    price  }}将会返回:{  "data": {    "products": [          {        "id": 100,        "name": "My amazing product",        "price": 400      }    ]  }}

登录后复制

很好,按照预期工作了。现在可以根据需要获取字段了。你可以试着添加一些描述:

query{  products{    id,    name,    description,    price  }}

登录后复制

现在我们可以对product进行描述。接下来试试user吧。

mutation{  user(id:200,  firstName:"Marcos",  lastName:"Silva",  password:"amaz1ingP4ss",  permissionLevel:9,  email:"marcos.henrique@toptal.com") {    id  }}

登录后复制

查询如下:

query{  users{    id,    firstName,    lastName,    password,    email  }}

登录后复制

返回内容如下:

{"data": {  "users": [    {     "id": 200,     "firstName": "Marcos",     "lastName": "Silva",     "password": "kpj6Mq0tGChGbZ+BT9Nw6RMCLReZEPPyBCaUS3X23lZwCCp1Ogb94/                           oqJlya0xOBdgEbUwqRSuZRjZGhCzLdeQ==",     "email": "marcos.henrique@toptal.com"     }   ]}}

登录后复制

到此为止,我们的GraphQL骨架完成!虽然离实现一个有用的、功能齐全的API还需要很多步骤,但现在已经设置好了基本的核心功能。

总结和最后的想法

让我们回顾一下本文的内容:

在Node.js下可以通过Express和GraphQL库来构建GraphQL API;基本的GraphQL使用;查询和修改的基本用法;为项目创建模块的基本方法;测试我们的GraphQL API;

为了集中精力关注GraphQL API本身,我们忽略了几个重要的步骤,可简要总结如下:

新项目的验证;使用通用的错误服务正确处理异常;验证用户可以在每个请求中使用的字段;添加JWT拦截器以保护API;使用更有效的方法处理密码哈希;添加单元和集成测试;

请记住,我们在Git (https://github.com/makinhs/node-graphql-tutorial)上有完整的源代码。可以随意使用、fork、提问、pull 并运行它!请注意,本文中提出的所有标准和建议并不是一成不变的。

这只是设计GraphQL API的众多方法之一。此外,请务必更详细地阅读和探索GraphQL文档,以了解它提供的内容以及怎样使你的API更好。

英文地址原文:https://www.toptal.com/graphql/graphql-nodejs-api

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

以上就是创建安全Node.js GraphQL API的快速指南的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2725990.html

(0)
上一篇 2025年3月7日 23:28:15
下一篇 2025年2月26日 13:07:05

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 详解Node.js Buffer的使用

    JavaScript 起初为浏览器而设计,没有读取或操作二进制数据流的机制。Buffer类的引入,则让NodeJS拥有操作文件流或网络二进制流的能力。【视频教程推荐:node js教程 】 Buffer基本概念 Buffer 对象的内存分配…

    2025年3月7日
    200
  • 用Node.js如何快速构建一个API服务器?

    Node.js 对初学者来说可能是令人望而却步的,其灵活的结构和缺乏严格的规范使它看起来很复杂。【视频教程推荐:node js教程 】 本教程是 Node.js,Express 框架和 MongoDB 的快速指南,重点介绍基本的 REST …

    2025年3月7日 编程技术
    200
  • nodejs适合做些什么?

    nodejs适合做什么 我们学习完一门新的技术,我们要知道它适用于什么场景。 nodejs可以说是,极客追求极致性能的产物,缺少服务器健壮性的考虑。不建议使用在追求稳定的业务上,如银行、证券、电信系统等。 【视频教程推荐:node js教程…

    2025年3月7日
    200
  • nodejs版的orm库–sequelize

    本篇文章带大家了解一下nodejs数据库orm扩展-sequelize。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 sequelize是nodejs版的orm库,用过laravelORM的能很快能上手 【视频教程推荐:…

    2025年3月7日
    200
  • Mac和Windows下如何使用nvm安装和管理多个版本的node.js?

    本篇文章带大家了解mac和windows下使用nvm安装和管理多个版本的node.js的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 写在前面的话 目前安装 Node.js 的方式主要有以下两种。【视频教程推荐:n…

    2025年3月7日
    200
  • nodejs有什么用?

    Nodejs框架是基于V8的引擎,是目前速度最快的 Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮 助我们迅速建立web站点,比起PHP的开发…

    2025年3月7日
    200
  • nodejs、npm、nvm三者有什么关系?

    掌握nodejs、npm、nvm三者之间的关系,就能了解reactnative项目是如何进行模块化构建的。下面本篇文章就来带大家了解一下nvm、npm、nodejs的关系。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 视…

    2025年3月7日
    200
  • 使用源码如何编译安装nodejs?

    视频教程推荐:node js教程  有个站友在看我写的VisualEditor安装笔记时,碰到了NodeJs的版本问题。 简述一下我的安装过程。我当时用的是v6.9.5,现在看来下最新的已经到了v6.10.0了,其实都差不多。 先到 Nod…

    2025年3月7日
    200
  • nodejs接口如何传输数据?

    视频教程推荐:node js教程  最近项目需要接口传输,于是乎找了那个选择哪个语言,选择node,而且是https模式!找了好久才解决跨域问题!废话不多说,直接上代码 let mysql = require(‘mysql’);let ex…

    2025年3月7日
    200
  • 详解Nodejs Express.js项目架构

    视频教程推荐:nodejs 教程  引言 在 node.js 领域中,Express.js 是一个为人所熟知的 REST APIs 开发框架。虽然它非常的出色,但是该如何组织的项目代码,却没人告诉你。 通常这没什么,不过对于开发者而言这又是…

    2025年3月7日
    200

发表回复

登录后才能评论