Django urlsafe base64解密与解密

Enc*_*ner 18 python encryption django base64 encoding

我正在为用户注册编写自己的验证码系统.所以我需要创建一个合适的URL来接收生成的验证码图片.一代看起来像这样:

_cipher = cipher.new(settings.CAPTCHA_SECRET_KEY, cipher.MODE_ECB)
_encrypt_block = lambda block: _cipher.encrypt(block + ' ' * (_cipher.block_size - len(block) % _cipher.block_size)) 
#...
a = (self.rightnum, self.animal_type[1])
serialized = pickle.dumps(a)
encrypted = _encrypt_block(serialized)
safe_url = urlsafe_b64encode(encrypted)
Run Code Online (Sandbox Code Playgroud)

但后来我试图通过视图函数中的GET请求接收此密钥,它在urlsafe_b64decode()上失败,"字符映射必须返回整数,无或unicode"错误:

def captcha(request):
  try:
    key = request.REQUEST['key']
    decoded = urlsafe_b64decode(key)
    decrypted = _decrypt_block(decoded)
    deserialized = pickle.loads(decrypted)
    return HttpResponse(deserialized)
  except KeyError: 
    return HttpResponseBadRequest()
Run Code Online (Sandbox Code Playgroud)

我发现在urlsafe_b64encode的输出上有一个str,但是GET请求返回一个unicode对象(不过它是一个正确的字符串).Str()没有帮助(它在django内部返回解码错误),如果我使用密钥.repr它工作,但解密器不能使用错误"输入字符串必须是16的倍数".在测试文件里面所有这些结构都很完美,我无法理解,有什么不对?

Jef*_*ris 36

问题是b64decode非常明确地只能占用字节(字符串),而不是unicode.

>>> import base64
>>> test = "Hi, I'm a string"
>>> enc = base64.urlsafe_b64encode(test)
>>> enc
'SGksIEknbSBhIHN0cmluZw=='
>>> uenc = unicode(enc)
>>> base64.urlsafe_b64decode(enc)
"Hi, I'm a string"
>>> base64.urlsafe_b64decode(uenc)
Traceback (most recent call last):
...
TypeError: character mapping must return integer, None or unicode
Run Code Online (Sandbox Code Playgroud)

由于您知道您的数据仅包含ASCII数据(这将是base64encode将返回的数据),因此将您的unicode代码点编码为ASCII或UTF-8字节应该是安全的,这些字节将等同于您期望的ASCII.

>>> base64.urlsafe_b64decode(uenc.encode("ascii"))
"Hi, I'm a string"
Run Code Online (Sandbox Code Playgroud)

  • 这有助于我在python web服务器中遇到的相关问题. (2认同)