为什么将分页游标或id值编码为字符串是一种常见做法?

ste*_*eak 10 base64 cursor facebook-graph-api

例如Facebook Graph API:为什么afterbeforebase64编码的数字?

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}
Run Code Online (Sandbox Code Playgroud)

与普通数字相比,它可能带来什么好处呢?

如下面的python日志所示,优点不能是数据的简短表示或包含不安全字符的数据:

>>> base64.b64decode("MTAxNTExOTQ1MjAwNzI5NDE=")
'10151194520072941'
>>> len('10151194520072941')
17
>>> len("MTAxNTExOTQ1MjAwNzI5NDE=")
24
Run Code Online (Sandbox Code Playgroud)

Ter*_*nen 5

根据 StackOverflow 中提出的问题,JavaScript 中可能的最大数字是 9007199254740992数字在不丢失精度的情况下可以达到的 JavaScript 最大整数值是多少?

如果您比较这些值

9007199254740992    // the JS maximum
10151194520072941   // the Base64 encoded number
Run Code Online (Sandbox Code Playgroud)

当然,看起来 Facebook 内部(出于我们不知道的原因)存储的值对于 JavaScript 数字精度来说太大了,无法处理。

因此,在我看来,他们除了将数字作为字符串处理之外别无选择。

当然,它们可以仅用作"10151194520072941"字符串格式的数字,但有些程序员可能会将其混淆为数字。尽管这种情况很少发生,但他们可能认为对数字进行 Base64 编码可以避免有人将字符串转换为整数的问题。

而且,由于这是公共API函数,并不是自己的工程师使用的,因此风险更大,因为使用该API的人来自不同的教育背景。他们可能会意外地使用例如 parseInt 或类似的数字,从而导致不必要的客户服务请求。

编辑:使用非常大的数字也可能有另一个目的:检测 API 的故意滥用。例如,如果他们使用随机 UUID 值或连续数值,则任何接近的值都可能是合法的。如果它是 UUID,他们首先必须发出请求以查看它是否是合法条目。拥有大量的数字基数,可能只有千分之一是合法的,或者它们遵循一些其他数学规则,这些规则可以由单个服务器检测到,而无需向其他服务器发出请求,从而筛选出故意制作具有非法值的请求的客户端变得更加困难有效的,也许可以在到达数据库之前被过滤掉。


Sau*_*sra 1

这是对问题的“为什么使用 base64 编码游标”部分的更一般的答案,与 Facebook Graph API 无关。

我同意Rafael Almeidarodrigomd 的观点,即 Base64 编码背后的目的是隐藏实现细节并保持光标值紧凑。

这是一种标准做法。

Slack 的人员使用 Base64 编码的游标,因为他们的游标值(编码前)看起来像这样:

user:W07QCRPA4
Run Code Online (Sandbox Code Playgroud)

Base64 编码该值使其保持紧凑并隐藏实现细节。

这也使他们能够灵活地使用相同的策略,通过使用游标值将基于偏移量的分页 API 服务转换为基于游标的 API 服务:

offset:10
Run Code Online (Sandbox Code Playgroud)

客户不会知道其中的区别,因为他们不需要。