2010-02-09 48 views
16

Tôi đang viết hệ thống captcha của riêng mình để đăng ký người dùng. Vì vậy, tôi cần phải tạo một URL phù hợp để nhận ảnh được tạo bằng hình ảnh xác thực. Thế hệ trông như thế này:Giải mã base64 của Django urlsafe với giải mã

_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) 

Nhưng sau đó tôi đang cố gắng để nhận khóa này qua yêu cầu GET trong hàm xem, nó không thành công trên urlsafe_b64decode() với "bản đồ nhân vật phải trả lại số nguyên, Không có hoặc unicode" lỗi:

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() 

tôi thấy rằng trên đầu ra của urlsafe_b64encode có một str, nhưng GET yêu cầu trả về một đối tượng unicode (tuy nhiên nó là một chuỗi bên phải). Str() đã không giúp đỡ (nó trả về lỗi giải mã sâu bên trong django), và nếu tôi sử dụng khóa. repr nó hoạt động, nhưng bộ giải mã không hoạt động với lỗi "Chuỗi đầu vào phải là bội số của độ dài 16". Bên trong một tập tin kiểm tra tất cả các công trình xây dựng này hoạt động hoàn hảo, tôi không thể hiểu, có gì sai?

+0

Mã hóa có cần thiết không? Không thể tạo captcha lưu trữ câu trả lời chính xác ở phía máy chủ dữ liệu phiên? Hay bạn đang cố tránh điều đó? – MattH

+0

Chưa nghĩ về nó. Nhưng vấn đề này rất thú vị và tôi muốn hiểu tại sao nó lại vui vẻ. – Enchantner

+0

'key = str (request.REQUEST ['key'])' không hoạt động? – MattH

Trả lời

32

Vấn đề là b64decode khá rõ ràng chỉ có thể lấy byte (một chuỗi), không phải 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 

Vì bạn biết rằng dữ liệu của bạn chỉ chứa dữ liệu ASCII (đó là những gì base64encode sẽ trở lại), nó phải là an toàn để mã hóa các điểm mã unicode của bạn như ASCII hoặc UTF-8 byte, những byte sẽ tương đương với ASCII bạn mong đợi.

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

Điều này giúp cho một vấn đề liên quan mà tôi có trong máy chủ web python. – hughdbrown

+1

"bạn biết rằng dữ liệu của bạn chỉ chứa dữ liệu ASCII" - và đó là lý do tại sao tôi sẽ viết '.encode (" ascii ")'. –

+0

Có, "ascii" sẽ tốt hơn. Đã cập nhật. –

3

Tôi đã giải quyết được sự cố!

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

Nhưng tôi vẫn không hiểu, tại sao lần đầu tiên nó không hoạt động.

Các vấn đề liên quan