用签名保护你的隐私(3)-URL安全序列化

用签名保护你的隐私(3)-URL安全序列化

在网络上进行数据传输是不安全的,必须的防止数据的伪造和篡改,特别是在web开发中使用GET传参的时候就更加要考虑这种需求,但GET传参是通过URL传参的,只能使用ASCII码,Itsdangerous模块中的URL安全序列化正好满足这种字符受限的情况。

URL安全序列化包括以下两个类:

  • URLSafeSerializer
  • URLSafeTimedSerializer

1.URLSafeSerializer

这个类的用法同Serializer差不多,但可以序列化和反序列化url安全的字符串,包括大小写英文字母和'_'、'-'、'.'

图1 URLSafeSerializer继承层次

从继承的层次看URLSafeSerializer多了一个父类URLSafeSerializerMixin,这类功能是什么呢?下面是它的源码

class URLSafeSerializerMixin(object):
    default_serializer = _CompactJSON

    def load_payload(self, payload, *args, **kwargs):  # 反序列化预处理
        decompress = False
        if payload.startswith(b"."):
            payload = payload[1:]
            decompress = True
        try:
            json = base64_decode(payload)  # base64解码
        except Exception as e:
            raise BadPayload(
                "Could not base64 decode the payload because of an exception",
                original_error=e,
            )
        if decompress:
            try:
                json = zlib.decompress(json)   # 解压缩
            except Exception as e:
                raise BadPayload(
                    "Could not zlib decompress the payload before decoding the payload",
                    original_error=e,
                )
        return super(URLSafeSerializerMixin, self).load_payload(json, *args, **kwargs)

    def dump_payload(self, obj):  # 序列化预处理
        json = super(URLSafeSerializerMixin, self).dump_payload(obj)
        is_compressed = False
        compressed = zlib.compress(json)    # 关键,压缩字符串
        if len(compressed) < (len(json) - 1):
            json = compressed
            is_compressed = True
        base64d = base64_encode(json)  # 对字符串做base64编码
        if is_compressed:
            base64d = b"." + base64d
        return base64d

从源代码看,这个类主要完成序列化和反序列化的预处理,在序列化预处理中,对要序列化的字符串进行压缩,然后再进行base64编码。所以它的子类URLSafeSerializer可以对特殊字符(_-.)进行处理。URLSafeSerializer用法和Serializer相同,如图2所示

图2 URLSafeSerializer用法

2.URLSafeTimedSerializer

这个类和TimedSerializer用法差不多,但序列化(dumps)和反序列化(loads)url安全的字符串,包括大小写英文字母和'_'、'-'、'.'

图3 URLSafeTimedSerializer继承层次

URLSafeTimedSerializer也继承了URLSafeSerializerMixin,它会对字符串进行base64编码,所以也可以处理特殊字符。下面是它的用法:

import time

from itsdangerous.url_safe import URLSafeTimedSerializer

url_time_serializer = URLSafeTimedSerializer('ksdfkls903')

# 序列化
res = url_time_serializer.dumps([1,2,3])
# WzEsMiwzXQ.XoBQLA.0fRHds5_DwWfVqeorMSOU4ohz0U
print(res)

# 反序列化
# 没有时间限制
res = url_time_serializer.loads(res)
# [1, 2, 3]
print(res)

time.sleep(5) # 等等5秒

# 有时间限制
res = url_time_serializer.loads(res,max_age=3)
print(res)

其执行结果如图4所示。

图4 执行结果

URLSafeTimedSerializer可以对各种内置类型进行序列化,生成URL安全的字符串,并且可以限制过期时间,是非常理想的生成token的算法,所以在前后端分离的项目总可以使用URLSafeTimedSerializer生成token,在下一节中,我们将讨论token的生成。

喜欢的话请记得收藏点赞

发布于 2020-03-30 20:02