Base62x跨版本跨编程语言的一致性

全中国已经是2022年的隆冬三九,冬天已经来临,春天还会远吗?拿命硬扛地中华儿女正以巨大的牺牲从新冠肺炎疫情的寒冬中艰难困苦地走向新的春天。

我们大约在三年前写下《gMIS吉米斯升级支持IPv4/IPv6双栈网络模式》( https://ufqi.com/blog/gmis-with-ipv4-ipv6-dual-stack/ )一文,简述了在单用户多网络路径的情况下用户基于IP地址鉴权的问题。这类问题的根本原因在于网络基础设施的发展与发达,单一用户可能在多个通信网络间漫游,从而其通信IP地址也不断变化;其次,还在于单一用户可能同时具有不同通信网络的接入通道,从而同时具备了多网络IP的通信能力。

该文的解决思路里也提到在 Base62x, 用于编解码单用户多IP地址的地址编码、安全ID编码等。文章进一步地阐述,今后所有网络应用都将面临这类问题。
最近,我们的所经历的一起网络应用的故障排解过程就应验了这一预见。

有福常在UfqiLong 是我们主力推荐的一个内容推选阅读平台。UfqiLong的用户在发起内容推荐时,需要进行用户身份识别和安全性校验。UfqiLong的用户鉴权是基于 有福工坊UfqiWork的用户服务模块。
UfqiLong是使用PHP写成的程序,而UfqiWork是基于Java语言编制的。他们之间的用户鉴权的传递,依靠用户安全号(Sid).

这次遇到的问题是这样的,我们通过Java语言的接口将用户安全Sid写入到Cache服务,通过Java也能够读取出来已经写入的目标数据。但是通过PHP的接口读取相应的Sid的已经Cache的数据时,总是报错说读取不到。
问题先排除不是Cache服务本身的错误,因为通过Java语言和Cache服务的命令行读取方式,都能够获取相应的数据,而通过PHP语言的接口却无法读取到所Cache的对应的数据。
进一步地分析发现,PHP接口的 Cache读取服务返回的代码表示为 NotFound, Cache服务确实没有找到的 Key 所对应的 Value.

很快问题被 Narrow down到被检索数据的 Key上。无论是 Java 的 Cache服务的 Key , 还是 PHP 接口程序读取 Cache 所使用到的 Key, 都经过了相应的处理,其中对 Key 的处理上,都用到了 Base62x .
Bug被进一步地迁转到 Java版本的 Base62x 和 PHP版本的 Base62x 对相应的 Key进行编码时是否一致,也即 Base62x 的跨版本、跨编程语言的一致性问题。

Base62x 在算法设计上相对简单,采用 64进制的数字编码,码表为 0-9A-Za-z, x1, x2, x3.

在 UfqiLong 的跟踪日志上,很快定位到问题的病灶,Java版本的 Base62x 对 Cache服务所处理的数据的 Key进行编码时,使用的“长度优化”的策略,使用该策略,对纯ASCII字符(0~127,8bits, 1byte以内的范围)进行简单地处理,不做字节及bit操作。比如,字符串 ABCD会被编码为 ABCDx .
ABCD –> 字符串长度优化地 Base62x编码 –> ABCDx

Base62x 还要额外的选项,表示纯数字进制的转换,比如 16进制的数字 ABCD(十进制的 43,981),会被转码为 64进制的数字,转码为64进制的数字后,使用 Base62x表达这一数字是 AlD .
ABCD –> 纯数字进制地 Base62x编码 –> AlD

Base62x 多编码策略

字符串 ABCD 使用最传统的 Base64编码方案的输出为 “QUJDRA==” 。

在 UfqiLong的PHP的 Cache服务接口程序中,PHP的 Base62x 使用了“纯数字进制”的策略。于是问题就产生了。在 Java接口程序和 PHP接口程序读写同一个 Cache服务时,Java写入的 Cache数据,Key=ABCDx, 而 PHP接口程序读取 Cache数据时,Key=AlD 。

Base62x 在编码实现上,力争做到向下兼容,也即后一个版本的总是最大限度地兼容前一个版本,版本的改进主要是性能优化和功能改进。
Base62x在编码实现上,也力争做到跨编程语言的一致性,也即对于同一字符串,使用不同编程语言的实现,其最终输出的被编码的字符串应该是严格高度的一致。
基于这两点, Base62x 在被创制以来,才不断地扩大应用部署范围,日益在更加广泛的软件研发中实现对传统 Base64及其各个变种取代和替换,同时也在替换传统意义上的 Base62 .

除了上面说的这一点, 关于 Base62x 在编码时,对纯 ASCII字符串的处理上,有两种截然不同的策略选择——长度优化的方法和数字进制的方法。
在 Base62x 0.7 及较早的版本中,没有选择,所有的输出都是 数字进制转换的处理方法。
在 Base62x 0.8 及之后的版本中,Base62x 针对纯 ASCII字符串,提供了额外的长度优化的方法,而且这一方法,被设置为默认启用,取代了之前的 数字进制转换的处理方法。

UfqiLong这次遇到的技术 Bug,其原因就是 UfqiLong使用了较早版本的 Base62x的 PHP版本,默认是对纯 ASCII字符串进行数字进制转换的方法;而 UfqiWork则使用了较新版本的 Base62x的 Java版本。 后者默认对纯 ASCII字符串进行长度优化的处理方法。

这种不兼容,显然是软件升级迭代过程中的一次失误。应该在后续极力避免。这一早期版本与后期版本不兼容的问题,只能随着时间的推移,由开发人员在后续升级更新后逐步消除。


base62x
Base62x

Base62x: An alternative approach to Base64 for alphanumeric-only [a-zA-Z0-9] characters in output.
Base62x is an non-symbolic Base64 encoding scheme. It can be used safely in computer file systems, programming languages for data exchange, internet communication systems, etc, and it is an ideal substitute and successor of tradtional Base64 and many variants of Base64 encoding scheme.

Base62x 是一种无符号 [a-zA-Z0-9] 的Base64编码方案。
她可以在计算机文件系统、编程语言数据交换、互联网络通信系统等方面安全地使用,同时是传统算法和各种变种Base64编码方案的理想替代品、继任者。

此条目发表在-gMIS, Base62x, 编程技术, 计算机技术分类目录,贴了, , , , 标签。将固定链接加入收藏夹。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code