Django urlsafe base64 декодирование с расшифровкой

Я пишу собственную систему captcha для регистрации пользователя. Поэтому мне нужно создать подходящий URL для получения сгенерированных изображений captcha. Поколение выглядит так:

_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 (), когда «сопоставление символов должно возвращать целое число, None или 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() 

Я обнаружил, что на выходе urlsafe_b64encode есть str, но GET-запрос возвращает объект unicode (тем не менее, это правильная строка). Str () не помогло (он возвращает ошибку декодирования глубоко внутри django), и если я использую ключ. он работает, но дешифратор не работает с ошибкой «Строки ввода должны быть кратными 16 в длину». Внутри тестового файла вся эта конструкция прекрасно работает, я не могу понять, что случилось?

    Проблема в том, что 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 

    Поскольку вы знаете, что ваши данные содержат только данные ASCII (это то, что base64encode вернет), должно быть безопасно кодировать ваши кодовые точки юникода в виде байтов ASCII или UTF-8, эти байты будут эквивалентны ожидаемому ASCII.

     >>> base64.urlsafe_b64decode(uenc.encode("ascii")) "Hi, I'm a string" 

    Я решил проблему!

     deserialized = pickle.loads(captcha_decrypt(urlsafe_b64decode(key.encode('ascii')))) return HttpResponse(str(deserialized)) 

    Но все же я не понимаю, почему это не сработало в первый раз.