隐藏 ID
比如数据库主键自增ID, UUID
,MongoDB 的ObjectId
等,你不希望用户看到。可以使用sqids
方案。
Sqids (pronounced “squids”) is a small library that lets you generate unique IDs from numbers. It’s good for link shortening, fast & URL-safe ID generation and decoding back into numbers for quicker database lookups.
它可以通过自定义字母表来达到别人无法破解你的数据。
sqids = Sqids(alphabet="FxnXM1kBN6cuhsAvjW3Co7l2RePyY8DwaU04Tzt9fHQrqSVKdpimLGIJOgb5ZE")
id = sqids.encode([1, 2, 3]) # "B4aajs"
numbers = sqids.decode(id) # [1, 2, 3]
只要使用不同的的 alphabet
就可以了,在它的官网页面下方有个小工具,可以随机生成一个独特的字母表,刷新一下,然后复制到你的代码里,就谁也猜不透你的小心思。
这个很有用,比如你的数据表使用自增 ID,那么使用sqids
加密以后,1
就可能变成了Uk
(注:不同的字母表会不同),而2
则是gb
,小的数字变化结果差异还非常大。如果你使用一些小技巧,比如在 ID 前面加多个秘密数字,比如 100,那么1
就变成了6VEgb
,而2
则是TdK1E
,更加难猜了,能有效避免别有用心的人通过数字增加直接扫描你的数据表。
因为 sqids 只针对数字序列有效,所以如果你用的是 UUID
或 ObjectId
等,就需要把它转化为数字序列,这个很容易,不同的编程语言都有很好的支持。比如在Python
中你可以使用int.from_bytes()
和int.to_bytes()
(注:需要注意不同版本之间的参数差异)。
隐藏比较长的信息
比如一个JSON
对象,或者一段URL
,这在你做跳转功能的时候很有用。
举个例子,登陆以后跳转回原网址,而登陆又在SSO
的另一边,那么可能会有很多信息一层一层加上去,如果在代码中详细地处理,当跳转的规则变化时,SSO
可能不得不为了子站的功能而修改代码。这个时候就可以使用JSON
把下游信息打包传过来,达到解偶的目标。
这个方案是使用jwt
,对的,就是登陆的那个jwt
。
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
在它的官网你可以看到这样的例子,有一个数据:
{"sub": "1234567890","name": "John Doe","iat": 1516239022
}
打包编码之后是这样的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这段代码在别人不知道你的加密密钥的时候,是无法解密的。这样你在业务就可以把打包编码后的内容附到网址URL里,而SSO
之类的上游在跳转的时候只要把这个参数继续传回,你解码之后就可以按自己的方式继续处理,当你增加或变更字段的时候,就不需要上游配合。
除了使用对称加密方法外,也可以使用RSA
等不对称加密算法,你只要把公钥发给业务方,那么他就可以加密传输数据给你,而第三方是不可见的。
在Python
编程中,你可以使用pyjwt
库,代码非常简单:
>>> import jwt
>>> key = "secret"
>>> encoded = jwt.encode({"some": "payload"}, key, algorithm="HS256")
>>> print(encoded)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
>>> jwt.decode(encoded, key, algorithms="HS256")
{'some': 'payload'}
最后
这两个方案都是很多编程语言支持的,在此仅使用Python
为例,实践中可以找一下自己熟悉的编程语言的相关库来用。