当前位置: 首页 > news >正文

什么是GraphQL?

如果你在寻找漏洞利用方式,请参考下面的文章

GraphQL API 漏洞 |网络安全学院
GitHub - swisskyrepo/PayloadsAllTheThings: A list of useful payloads and bypass for Web Application Security and Pentest/CTF

GraphQL 查询(Query)

GraphQL 既不是架构,也不是数据库。它是一种 查询语言运行时环境,用于 API 的数据查询和操作。

假设你有一个使用关系型数据库(如 MySQL 或 PostgreSQL)的应用,数据库中存储了用户信息和文章数据。你可以通过 GraphQL 构建一个 API,它允许客户端按需查询用户信息和文章内容:

  • 你可以通过 GraphQL 查询来请求某个用户的基本信息和他的文章:
    {
      user(id: 1) {
        name
        email
        posts {
          title
          content
        }
      }
    }
  • GraphQL 会将这个请求转发到服务器端,服务器端会通过数据库查询(例如 SQL 查询)获取数据,然后将结果返回给客户端。

响应可能看起来是这样的

{
  "data": {
    "user": {
      "name": "张三",
      "email": "zhangsan@example.com",
      "posts": [
        {
          "title": "GraphQL简介",
          "content": "GraphQL是一种用于API的查询语言和运行时环境。"
        },
        {
          "title": "Apollo Server使用指南",
          "content": "Apollo Server是一个用于构建GraphQL服务器的库。"
        }
      ]
    }
  }
}

所以,GraphQL 是一种 灵活的数据查询工具,它位于应用的 API 层,能让客户端高效地与不同的数据源交互,但它本身不负责数据库的存储和管理。

GraphQL 结构与类型信息

在 GraphQL 中,结构类型信息 主要指的是 API 中的 数据模型查询接口,它们描述了你可以查询的数据的组织形式和每个数据字段的类型。通过这些信息,客户端能够了解如何正确地查询 API,以及 API 返回的每个字段的数据类型是什么。下面是对这些术语的详细解释。

1. GraphQL API 的结构

结构 指的是 GraphQL 服务的 整体设计,包括:

  • 类型(Types):GraphQL API 中定义的各种数据类型。例如,UserPostComment 等,通常表示你在应用中处理的数据模型。
  • 字段(Fields):每个类型下的字段,这些字段是 GraphQL 查询的结果。例如,一个 User 类型可能有 idnameemail 等字段。
  • 查询(Queries)变更(Mutations)订阅(Subscriptions):这些是你可以对 API 执行的操作。查询用于获取数据,变更用于修改数据,订阅用于实时接收数据更新。

2. GraphQL API 的类型信息

类型信息 指的是 API 中各个类型的具体定义和它们之间的关系。这些信息包括:

2.1 基本类型(Scalar Types)

GraphQL 提供了几种基本的标量类型,用于描述单一值的类型:

  • Int:整数
  • Float:浮动点数
  • String:字符串
  • Boolean:布尔值(truefalse
  • ID:唯一标识符,通常用作主键(类似于 UUID
2.2 对象类型(Object Types)

对象类型是 GraphQL 中最常见的类型,用于定义一个包含多个字段的数据结构。例如,一个 User 类型可能定义如下:

type User {
  id: ID!
  name: String!
  email: String
  posts: [Post]
}
  • User 类型包含了几个字段,如 id(ID 类型,必需)、name(String 类型,必需)、email(String 类型,非必需)、posts(一个 Post 类型的数组,表示该用户的所有帖子)。
  • ID! 表示 id 字段是必需的(非 null)。
  • posts 字段是一个 数组,并且是 Post 类型的数组,这意味着每个用户可能有多个帖子。
2.3 输入类型(Input Types)

输入类型用于描述查询或变更请求中传递的数据结构。例如,一个 CreateUser 类型可以定义如何创建一个用户:

input CreateUser {
  name: String!
  email: String!
}
  • CreateUser 类型定义了创建用户时需要提供的字段,nameemail 都是必需的。
2.4 枚举类型(Enum Types)

枚举类型用于定义一组固定的值。例如,定义用户角色的枚举类型:

enum Role {
  ADMIN
  USER
  GUEST
}
  • Role 枚举类型包含了三个可能的值:ADMINUSERGUEST,这些可以用于限制字段的输入值。
2.5 接口类型(Interface Types)

接口类型允许你定义一组共享字段的类型。比如,我们可以定义一个 Node 接口,使得多个类型都继承这个接口,保证它们有相同的字段:

interface Node {
  id: ID!
}

type User implements Node {
  id: ID!
  name: String!
}

type Post implements Node {
  id: ID!
  title: String!
}
  • Node 接口有一个 id 字段,任何实现了这个接口的类型(如 UserPost)都必须拥有 id 字段。
2.6 联合类型(Union Types)

联合类型允许一个字段返回多种类型中的任意一种。与接口类似,但联合类型不强制实现相同的字段,只是定义了多个可能返回的类型:

union SearchResult = User | Post
  • SearchResult 可以是 UserPost,具体返回哪一个类型由实际查询的结果决定。

GraphQL 内省(Introspection)

GraphQL 内省(Introspection) 是 GraphQL 的一个强大特性,它允许客户端查询 GraphQL API 的 结构类型信息,而不仅仅是查询应用程序的数据。通过内省,客户端可以动态地了解 GraphQL API 的模式、类型、查询、变更等元数据。

内省的工作原理

GraphQL 内省是通过一种特别的查询实现的,通常叫做 内省查询(Introspection Query)。这些查询返回关于 GraphQL API 的详细信息,比如:

  • 类型:查询支持的类型(如 QueryMutationSubscription 类型及其字段)。
  • 字段:每个类型下的字段及其类型。
  • 输入类型:GraphQL API 中支持的输入类型。
  • 枚举类型:GraphQL API 中定义的枚举类型及其可能的值。
  • 错误信息:每个字段可能返回的错误类型。

简单来说,内省使得客户端能够自我探索 API 的结构,而不需要依赖文档或其他外部信息。

一个典型的内省查询例子

一个典型的内省查询示例如下:

{
  __schema {
    types {
      name
    }
  }
}

这个查询会返回所有在 GraphQL API 中定义的类型的名称。你可以利用内省查询获得更详细的信息,比如查看每个类型的字段、字段的返回类型、查询或变更的定义等。

常见的内省查询示例

  1. 获取所有类型

    {
      __schema {
        types {
          name
        }
      }
    }
    

    这个查询返回 API 中的所有类型。

  2. 获取类型字段
    如果你想查询某个特定类型的字段,可以使用类似如下的查询:

    {
      __type(name: "User") {
        fields {
          name
          type {
            name
          }
        }
      }
    }
    

    这个查询返回 User 类型的字段及其类型。

  3. 获取某个字段的详细信息
    比如查询某个字段的数据类型和输入类型:

    {
      __type(name: "User") {
        fields {
          name
          args {
            name
            type {
              name
            }
          }
        }
      }
    }
    

某些 GraphQL 服务器允许禁用内省查询,尤其是在生产环境中,以提高安全性。例如,使用 Apollo Server 时,你可以通过设置 introspection 配置来禁用内省:

const server = new ApolloServer({
  schema,
  introspection: false, // 禁用内省
});

GraphQL 突变(Mutation)

GraphQL 突变(Mutation) 是 GraphQL 中的一种操作类型,用于 修改数据。与查询(Query)不同,查询用于 获取数据,而突变用于对数据进行 创建、更新或删除 操作。

1. 突变的基本概念

在 GraphQL 中,Mutation 是一种特定的操作类型,就像 Query 用来请求数据一样,Mutation 用来处理数据修改请求。每个突变操作通常会返回修改后的数据,或者返回表示操作结果的信息。

突变操作 的目标通常是数据库的更改,比如:

  • 创建一个新记录(如添加用户、发布文章等)。
  • 更新一个已有记录(如修改用户信息、修改文章内容等)。
  • 删除一个记录(如删除用户、删除文章等)。

2. GraphQL 突变的定义

在 GraphQL schema 中,Mutation 类型是专门用来定义数据修改操作的。例如:

type Mutation {
  createUser(name: String!, email: String!): User
  updateUser(id: ID!, name: String, email: String): User
  deleteUser(id: ID!): Boolean
}

这里定义了三个突变操作:

  • createUser:创建一个新的用户,返回一个 User 类型的对象。
  • updateUser:更新用户的信息,接受用户的 id 和可选的 nameemail,返回更新后的 User 对象。
  • deleteUser:删除一个用户,返回一个布尔值(truefalse),表示删除操作是否成功。

3. 突变的执行

执行突变时,你会发送一个包含特定操作和参数的请求。例如,要创建一个用户,你可以这样写:

mutation {
  createUser(name: "Alice", email: "alice@example.com") {
    id
    name
    email
  }
}

在这个突变请求中:

  • mutation 关键字表示这是一个突变请求。
  • createUser 是我们在 schema 中定义的突变操作。
  • nameemailcreateUser 操作需要的参数。
  • 你可以指定想要返回的字段,比如返回新创建的用户的 idnameemail

4. 突变的响应

执行突变后,服务器会返回执行结果。例如,上面的 createUser 突变成功时,服务器可能返回如下结果:

{
  "data": {
    "createUser": {
      "id": "1",
      "name": "Alice",
      "email": "alice@example.com"
    }
  }
}

返回的数据会包含你在请求中指定的字段(如 idnameemail)。

5. 突变的特点

  • 数据修改:突变通常用于改变数据的状态(创建、更新、删除)。
  • 副作用:突变操作通常会有副作用,可能涉及到数据库更新、缓存修改等。
  • 同步与返回:突变操作通常会返回修改后的数据,或者操作是否成功的反馈(如布尔值)。
  • 可以返回多个字段:虽然突变修改了数据,但你依然可以指定哪些字段返回给客户端,确保客户端可以在修改后获得最新的数据。

6. 突变和查询的区别

  • 查询(Query):用于 读取数据,无副作用,不会改变服务器上的任何数据。
  • 突变(Mutation):用于 修改数据,会产生副作用,可能涉及创建、更新、删除操作。

一个典型的查询请求示例:

query {
  getUser(id: "1") {
    id
    name
    email
  }
}

一个典型的突变请求示例:

mutation {
  updateUser(id: "1", name: "Alice Updated", email: "aliceupdated@example.com") {
    id
    name
    email
  }
}

7. 如何处理多个突变

GraphQL 允许你在一个请求中执行多个突变,但它们的执行是 顺序的,并且所有的突变都必须成功,才能返回一个完整的响应。比如,你可以在一个请求中同时更新用户的 nameemail

mutation {
  updateUser(id: "1", name: "Alice Updated") {
    id
    name
  }
  updateUser(id: "1", email: "aliceupdated@example.com") {
    id
    email
  }
}

8. 突变和错误处理

突变操作有可能会失败,通常由于参数不正确、数据不存在或者权限问题等。GraphQL 的错误处理机制允许返回详细的错误信息。例如,如果 updateUser 操作传入了无效的 id,响应可能如下:

{
  "errors": [
    {
      "message": "User not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["updateUser"],
      "extensions": {
        "code": "USER_NOT_FOUND"
      }
    }
  ],
  "data": null
}

相关文章:

  • Day45(补)【软考】2022年下半年软考软件设计师综合知识真题-计算机软件知识1
  • 电子制造企业数字化转型实战:基于Odoo构建MES平台的深度解决方案
  • DC-7靶机渗透测试全过程
  • 学习数据结构(10)栈和队列下+二叉树(堆)上
  • 机器学习实战(2):数据预处理——机器学习的第一步
  • C++效率掌握之STL库:string底层剖析
  • Zotero7 从下载到安装
  • K-均值(K-means)
  • LM Studio笔记
  • 使用 Vite + React 19 集成 Tailwind CSS 与 shadcn/ui 组件库完整指南
  • 日常知识点之遗留问题梳理(被问到用uml画设计模式)
  • Promise详解大全:介绍、九个方法使用和区别、返回值详解
  • 全面理解-c++11的引用折叠
  • PyQt6/PySide6 的 QPropertyAnimation 类
  • Golang GC 三色标记法
  • 多维度健康养生指南
  • 【计算机网络】网络层数据包(Packet)格式
  • 全方位养生指南:打造健康生活蓝图
  • vue-plugin-hiprint (vue2
  • 文本表示方法
  • 沪喀同心|为新疆青少年提供科普大餐,“小小博物家(喀什版)”启动
  • 秘鲁总理辞职
  • 马上评|“为偶像正名”的正确做法是什么
  • “异常”只停留在医院里,用艺术为“泡泡宝贝”加油
  • 来沪一个月几乎未花住宿钱,女子虚构卫生问题屡薅酒店羊毛被刑拘
  • 国台办:80年前台湾重归中国版图,80年后不可能让台湾分裂出去