Django urlsafe base64 解码与解密
我正在编写自己的验证码系统用于用户注册。所以我需要创建一个合适的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)
但后来我尝试通过视图函数中的 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()
我发现在输出上urlsafe_b64encode 有一个 str,但 GET 请求返回一个 unicode 对象(尽管如此,它是一个正确的字符串)。 Str() 没有帮助(它返回 django 内部深处的解码错误),如果我使用 key.repr 它可以工作,但解密器不能工作,并出现错误“输入字符串必须是多个长度为16”。 在测试文件中,所有这些构造都完美地工作,我不明白,出了什么问题?
I'm writing my own captcha system for user registration. So I need to create a suitable URL for receiving generated captcha pictures. Generation looks like this:
_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)
But then I'm trying to receive this key via GET request in the view function, it fails on urlsafe_b64decode() with "character mapping must return integer, None or unicode" error:
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()
I found that on the output of urlsafe_b64encode there is an str, but GET request returns a unicode object (nevertheless it's a right string). Str() didn't help (it returns decode error deep inside django), and if I use key.repr it works, but decryptor doesn't work with an error "Input strings must be a multiple of 16 in length".
Inside a test file all this construction works perfectly, I can't understand, what's wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是 b64decode 非常明确地只能接受字节(字符串),而不是 unicode。
由于您知道您的数据仅包含 ASCII 数据(这就是 base64encode 将返回的内容),因此将您的 unicode 代码点编码为 ASCII 或 UTF-8 字节应该是安全的,这些字节将相当于您期望的 ASCII。
The problem is that b64decode quite explicitly can only take bytes (a string), not unicode.
Since you know that your data only contains ASCII data (that's what base64encode will return), it should be safe to encode your unicode code points as ASCII or UTF-8 bytes, those bytes will be equivalent to the ASCII you expected.
我解决了问题!
但我仍然不明白,为什么第一次不起作用。
I solved the problem!
But still I don't understand, why it didn't work first time.