什么是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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/970230.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

案例-02.部门管理-查询

一.查询部门-需求 二.查询部门-思路 API接口文档 三.代码实现 1.controller层:负责与前端进行交互,接收前端所发来的请求 注:Slf4j用于记录日志使用,可以省略private static Logger log LoggerFactory.getLogger(DeptControlle…

小程序包体积优化指南:静态资源条件编译与分包编译技巧

在开发小程序时,可能大家都遇到过包体积超限的情况,这对多平台支持、用户体验和加载速度带来不少困扰。UniApp 提供了一些强大的功能,比如静态资源的条件编译和分包编译,这些功能可以帮助我们减少小程序的包体积,提高加…

12. QT控件:多元素控件

0. 概述 Qt中提供的多元素控件 QListWidget QListView QTableWidget QTableView QTreeWidget QTreeView xxWidget 和 xxView的区别 以QTableWidget 和 QTableView 为例: QTableView 是基于MVC设计的控件,QTableView自身不持有数据。使用QTableView需…

CAS单点登录(第7版)20.用户界面

如有疑问,请看视频:CAS单点登录(第7版) 用户界面 概述 概述 对 CAS 用户界面 (UI) 进行品牌化涉及编辑 CSS 样式表以及一小部分相对简单的 HTML 包含文件,也称为视图。(可选&…

android 的抓包工具

charles 抓包工具 官网地址 nullCharles Web Debugging Proxy - Official Sitehttps://www.charlesproxy.com/使用手册一定记得看官网 SSL Certificates • Charles Web Debugging Proxy http请求: 1.启动代理: 2.设置设备端口 3.手机连接当前代理 …

关于视频去水印的一点尝试

一. 视频去水印的几种方法 1. 使用ffmpeg delogo滤镜 delogo 滤镜的原理是通过插值算法,用水印周围的像素填充水印的位置。 示例: ffmpeg -i input.mp4 -filter_complex "[0:v]delogox420:y920:w1070:h60" output.mp4 该命令表示通过滤镜…

预测技术在美团弹性伸缩场景的探索与应用

管理企业大规模服务的弹性伸缩场景中,往往会面临着两个挑战:第一个挑战是精准的负载预测,由于应用实例的启动需要一定预热时间,被动响应式伸缩会在一段时间内影响服务质量;第二个挑战是高效的资源分配,即在…

【含开题报告+文档+PPT+源码】基于Spring+Vue的拾光印记婚纱影楼管理系统

开题报告 本论文旨在探讨基于Spring和Vue框架的拾光印记婚纱影楼管理系统的设计与实现。该系统集成了用户注册登录、个人资料修改、婚庆资讯浏览、婚庆套餐查看、婚纱拍摄预约、婚纱浏览与租赁、客片查看以及在线客服等多项功能,为用户提供了一站式的婚纱影楼服务体…

ASP.NET Core 使用 FileStream 将 FileResult 文件发送到浏览器后删除该文件

FileStream 在向浏览器发送文件时节省了服务器内存和资源,但如果需要删除文件怎么办?本文介绍如何在发送文件后删除文件;用 C# 编写。 另请参阅:位图创建和下载 使用FileStream向浏览器发送数据效率更高,因为文件是从…

字节跳动后端二面

📍1. 数据库的事务性质,InnoDB是如何实现的? 数据库事务具有ACID特性,即原子性、一致性、隔离性和持久性。InnoDB通过以下机制实现这些特性: 🚀 实现细节: 原子性:通过undo log实…

【个人开发】cuda12.6安装vllm安装实践【内含踩坑经验】

1. 背景 vLLM是一个快速且易于使用的LLM推理和服务库。企业级应用比较普遍,尝试安装相关环境,尝试使用。 2. 环境 模块版本python3.10CUDA12.6torch2.5.1xformers0.0.28.post3flash_attn2.7.4vllm0.6.4.post1 2.1 安装flash_attn 具体选择什么版本&…

19.4.9 数据库方式操作Excel

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 本节所说的操作Excel操作是讲如何把Excel作为数据库来操作。 通过COM来操作Excel操作,请参看第21.2节 在第19.3.4节【…

2024-2025年主流的开源向量数据库推荐

以下是2024-2025年主流的开源向量数据库推荐,涵盖其核心功能和应用场景: 1. Milvus 特点:专为大规模向量搜索设计,支持万亿级向量数据集的毫秒级搜索,适用于图像搜索、聊天机器人、化学结构搜索等场景。采用无状态架…

vue项目使用vite和vue-router实现history路由模式空白页以及404问题

开发项目的时候,我们一般都会使用路由,但是使用hash路由还是history路由成为了两种选择,因为hash路由在url中带有#号,history没有带#号,看起来更加自然美观。但是hash速度更快而且更通用,history需要配置很…

AI编程01-生成前/后端接口对表-豆包(或Deepseek+WPS的AI

前言: 做过全栈的工程师知道,如果一个APP的项目分别是前端/后端两个团队开发的话,那么原型设计之后,通过接口文档进行开发对接是非常必要的。 传统的方法是,大家一起定义一个接口文档,然后,前端和后端的工程师进行为何,现在AI的时代,是不是通过AI能协助呢,显然可以…

切换git仓库远程地址

1、首先可以先查看一下当前git库的远程地址 【cd .git】 切换到git目录【cat config】查看【cd ../】 返回项目目录 2、 切换到目标远程git地址 【git remote rm origin】 删除现有远程仓库 【git remote add origin url】添加新远程仓库 【cat .git/config】验证是否切换成功…

mapbox 从入门到精通 - 目录

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀总目录1.1 ☘️ mapbox基础1.2 ☘️…

前端包管理器的发展以及Npm、Yarn和Pnpm对比

在现代前端开发中,包管理器是不可或缺的核心工具。随着 JavaScript 生态的快速发展,开发者经历了从 npm 一统天下到 Yarn 挑战格局,再到 pnpm 创新突破的技术演进。这里将对三种主流包管理器(npm/Yarn/pnpm)进行全方位…

Qt QOpenGLWidget详解

1. 概述 QOpenGLWidget 是 Qt 框架中用于集成 OpenGL 渲染功能的类,它继承自 QWidget,允许开发者在 Qt 应用程序中轻松嵌入 OpenGL 图形。通过继承 QOpenGLWidget 并重写其虚函数(如 initializeGL()、resizeGL() 和 paintGL())&a…