[译] 怎样使用GraphQL - 进阶 - 4.安全

news/2024/7/3 18:36:59

英文原版地址:https://www.howtographql.com/...

GraphQL为客户端提供强大的能力。但是拥有强大的能力时,也会带来更大的风险。

由于客户端有可能使用非常复杂的查询,因此我们的服务器必须能够妥善处理。这些查询可能是来自恶意客户端的滥用查询,或者可能只是合法客户端使用的非常大的查询。在这两种情况下,客户端可能会将您的GraphQL服务器崩溃。

我们将在本章中介绍一些减轻这些风险的策略。我们将以最简单到最复杂的顺序来说明,并看看这些方式的利弊。

超时策略

第一个策略,也是最简单的策略是使用简单的超时来防范大型查询。这不需要服务器了解有关传入查询的任何内容。服务器需要知道的仅仅是允许查询的最长时间。

例如,配置了5秒超时的服务器将停止执行超过5秒钟执行的任何查询。

超时的优势

  • 操作简单

  • 大多数策略都会使用超时作为最终保护

超时的缺点

  • 即使有超时策略,也可能会造成不好的后果

  • 有时难以实施。在一段时间之后切断连接可能会导致奇怪的行为。

最大查询深度

正如我们之前所述,使用GraphQL的客户可以随意写出任意的复杂查询。由于GraphQL模式通常是嵌套的,这意味着客户端可以写出如下所示的查询:

query IAmEvil {
  author(id: "abc") {
    posts {
      author {
        posts {
          author {
            posts {
              author {
                # that could go on as deep as the client wants!
              }
            }
          }
        }
      }
    }
  }
}

如果我们可以阻止客户滥用这样的查询深度呢? 在了解定义的模式时,可以让你了解合法查询的深度。这实际上是可以实现的,并且通常称为最大查询深度。

通过分析查询文档的AST,GraphQL服务器能够根据其深度拒绝或接受请求。

例如,配置了最大查询深度为3的服务器,以及以下查询文档。红色方框选中的所有内容都被认为深度太深,查询无效。

图片描述

使用最大查询深度设置的graphql-ruby服务,我们得到以下返回结果:

{
  "errors": [
    {
      "message": "Query has depth of 6, which exceeds max depth of 3"
    }
  ]
}

最大查询深度优点

  • 由于静态分析了文档的AST,因此查询甚至不执行,所以不会在GraphQL服务器上增加负担。

最大查询深度缺点

  • 只有深度往往不足以涵盖所有滥用查询。 例如,在根节点上请求大量的查询将是代价巨大的,但不太可能被查询深度分析器阻止。

查询复杂性

有时,查询的深度还不足以真正了解GraphQL查询的开销。在很多情况下,我们的模式中的某些字段比其他字段更复杂。

查询复杂性允许您定义这些字段的复杂程度,并限制最大复杂度的查询。这个想法是通过使用一个简单的数字来定义每个字段的复杂程度。一个常见的默认设置是给每个字段一个复杂的1。以这个查询为例:

query {
  author(id: "abc") { # complexity: 1
    posts {           # complexity: 1
      title           # complexity: 1
    }
  }
}

一个简单的加法,告诉我们查询的复杂性是3。如果我们在我们的架构上设置最大复杂度为2,则此查询将会失败。

如果posts字段实际上比作者字段复杂度高很多呢?我们可以为该领域设置不同的复杂性。我们甚至可以根据参数设置不同的复杂性! 我们来看看一个类似的查询,其中posts会根据传入的参数去确定复杂性:

query {
  author(id: "abc") {    # complexity: 1
    posts(first: 5) {    # complexity: 5
      title              # complexity: 1
    }
  }
}

查询复杂性的优点

  • 可以覆盖比更多的用例。

  • 通过静态分析复杂性,在执行前拒绝查询。

查询复杂性缺点

  • 很难实现完美

  • 如果需要开发时预估复杂性,我们如何保持状态最新?我们一开始怎么能知道查询成本?

  • Mutations 很难估计。如果他们有一个难以衡量的附加操作,如在后台排队执行的任务怎么办?

节流

到目前为止,我们看到的解决方案都是会阻止滥用服务器的查询。像这样使用它们的问题是,它们会阻止大量查询,但不会阻止客户端生成出大量查询!

在大多数API中,使用简单的节流方式是,阻止客户端频繁地请求资源。GraphQL有点特别,因为调节请求数并没有真正帮助我们。即使是很少的请求也可能是大量的查询。

事实上,我们不知道客户端定义了多少请求是可以接受的。那么我们如何来限制客户端呢?

基于服务器执行时间的调节

我们可以通过查询执行时的服务器耗时,来估计查询的复杂程度。我们可以使用这种式来限制查询。凭借对系统的了解,您可以提出客户端可以在特定时间范围内使用的最大服务器时间。

我们还决定随着时间的推移,客户端添加多少服务器时间。这是一个经典的leaky bucket 算法。请注意,还有其他节流算法,但这些算法超出了本章的范围。在下面的例子中我们将使用leaky bucket。

让我们想象一下,我们将允许的最大服务器时间(Bucket Size)设置为1000ms,客户端每秒获得100ms的服务器时间(Leak Rate),mutation 如下:

mutation {
  createPost(input: { title: "GraphQL Security" }) {
    post {
      title
    }
  }
}

这个mutation平均需要200ms才能完成。实际上,时间可能会有所不同,但我们假设为了这个例子,它总是需要200ms才能完成。

这意味着在1秒内调用此操作超过5次的客户端将被阻止,直到更多的可用服务器时间添加到客户端。

经过两秒钟(100ms加秒),我们的客户可以一次调用createPost。

正如你所看到的,基于时间的调节是限制GraphQL查询不错的方式,因为复杂的查询将最终消耗更多的时间,这意味着你不能频繁地调用它们,而较小的查询可能被更频繁地调用,因为它们将非常快速地计算。

但如果GraphQL API是公开的,向客户端提出这些限制条件就不那么容易了。在这种情况下,服务器耗时并不能很好地告知客户端,客户端也不能准确的估计他们的查询所需要的时间,在不先试着请求的情况下。

还记得我们之前提到的最大复杂度?如果我们根据这个调节,会怎么样?

基于查询复杂度的调节

基于查询复杂度的调节是与客户端合作的好方法,客户端可以遵循schema中的限制。

我们使用与“查询复杂性”部分中使用的相同的复杂性示例:

query {
  author(id: "abc") {    # complexity: 1
    posts {              # complexity: 1
      title              # complexity: 1
    }
  }
}

我们知道这个查询的成本是基于复杂度的3。就像时间流逝一样,我们可以得知客户可以使用的每次最高成本(Bucket Size)。

如果最大成本为9,我们的客户只能三次运行此查询,不允许查询更多。

这些原理与我们的时间节制相同,但现在将这些限制传达给客户端后。客户甚至可以自己计算查询成本,而无需估计服务器时间!

GitHub公共API实际上使用这种方法来扼制客户端。看看他们如何对用户表达这些限制:https://developer.github.com/v4/guides/resource-limitations/。

总结

GraphQL非常适合用于客户端,因为给予了更多的功能。但是,强大的功能也带来了风险,担心客户端会以非常昂贵的查询来滥用GraphQL服务器。

有许多方法来保护您的GraphQL服务器免受这些查询,但是它们都不是万无一失的。重要的是,我们要知道有哪些方法可用来限制,并了解他们的优缺点,然后采取最优的决定!


http://www.niftyadmin.cn/n/1777154.html

相关文章

R语言pdf输出中文乱码处理

1、使用基础包。使用函数pdf()输出 在使用pdf()函数时,要输出中文,仅仅有一种字体可选。样例: pdf("chinese.pdf",family"GB1") plot(m2,xlab"高度",ylab"体重",main"统计") dev.off() 这…

java爬虫一(分析要爬取数据的网站)

一、获取你想要抓取的网站地址:http://www.zhaopin.com/然后打开控制台,F12,打开。我用的是Chrome浏览器,跟个人更喜欢Chrome的控制台字体。找到搜索栏对应的html标签:http://sou.zhaopin.com/jobs/searchresult.ashx?…

matlab打开弹出黑框后消失,matlab7.0安装时 为什么点击setup后弹出命令提示对话框,然后过三秒就消失了...

经典的错误啊 就是默认不支持AMD cpu 修改首先确认你的MATLAB的Matlab\bin\win32文件夹中有如下文件:atlas_Athlon.dll,然后 1.右击我的电脑-属性-高级-环境变量 2.在系统变量下面添加变量名:BLAS_VERSION 变量值:比如C:\Matlab\bin\win32\atlas_Athlon.dll (这个是…

一个api的 rt 大涨问题排查

mtop是移动接入网关平台,对客户端暴露api,后端接api实际的应用服务,有HSF,也有http的服务端。 之前进行了机房从杭州搬迁到上海,在搬迁的过程中,其中一个api的rt突然大涨,(之前平均的约210ms) 分…

提高未成年人网络安全意识的建议

随着网络的不断普及,人们在面对铺天盖地的网络信息时,普遍存在盲从现像,随之而来的是网络安全问题,尤其是未成年人网络安全,因为未成年人存在道德自律意识不高、道德认识过于感性化、理性程度、道德体验不足、缺乏选择…

从今天起,去做互联网

2020年 2019.11.27,来阿里快3年了,从流媒体视频领域换到了WebRTC领域,虽然这两个行业有点共同点,都是和音视频相关,都是和服务器相关,本质上直播是娱乐行业,WebRTC是通信行业,我也算…

linux文件系统空间扩容,linux下文件系统不丢数据扩容方法

已有分区/dev/sda6大小为1G,随着业务的增长,空间需求量变大,但又不能重新分区格式化,造成原有数据丢失。此时,可以使用resize2fs进行文件系统扩展,不影响分区中原有文件。具体步骤:(1)查看原分区…

算法笔记_233:二阶魔方旋转(Java)

目录 1 问题描述 2 解决方案 1 问题描述 魔方可以对它的6个面自由旋转。 我们来操作一个2阶魔方(如图1所示): 为了描述方便,我们为它建立了坐标系。 各个面的初始状态如下:x轴正向:绿x轴反向:蓝…