-
Django error: 'latin-1' codec can't encode characters in position 55-56: ordinal not in range(256)공부/오류 2023. 2. 27. 22:39
내용
해당 에러가 gunicorn으로 서버를 돌릴 때만 문제가 발생하게 되었다.
어디서 발생하는지 위치를 파악해본 결과 serializer.save() 에서 발생한다고 생각하였다.
그러나 계속 검색해보고 전문가의 조언으로 실마리를 찾을 수 있었다..
문제점
장고는 phone_number를 암호화 처리하여 저장하는 로직을 구현하였다.
해당 부분에서 발생하는 문제였다.
(gunicorn은 gunicorn은 문자 인코딩을 latin-1로 설정 되어있다고 한다.)
환경변수를 바꿔주고도 시도를 했지만 실패했다.(방법1. gunicorn --env LANG=en_US.UTF-8 tutorial.wsgi.local:application)
utf-8로 바꿔줘봤지만 실패(방법2. DEFAULT_CHARSET='utf-8')
힌트를 얻고 내가 처리한 암호화가 문제라고 생각
기존 암호화를 읽을 수가 없다고 하는거 같았다.
Cryptodom을 사용하였는데 해당 방식으로 왜 gunicorn이 정확하게 작동을 안하는지 원인 파악을 하지 못했다.
어떤 부분에서 encoding하지 못한다고 생각을 한다.
from Cryptodome.Cipher import AES --> from cryptography.fernet import Fernet
으로 변경하였다.
기존에 암호화 처리 했던 방식에서 몇가지만 수정해 주었다.
# encrypt_utils.py from cryptography.fernet import Fernet from tutorial.settings.base import KEY # 암호화 키 생성(한번 생성한 키는 계속 보관해야 한다.) # 이 키를 기반으로 복호화 하기때문에, # key = Fernet.generate_key() # 키 생성 부분 key = bytes(KEY,'utf-8') #바이트로 생성된 키를 # 암호화/복호화를 위한 Fernet 객체 생성 fernet = Fernet(key) def encrypt(phone_number): """핸드폰 번호를 암호화하는 함수""" # UTF-8 인코딩된 문자열을 바이트 문자열로 변환 phone_number_bytes = phone_number.encode('utf-8') # 암호화된 바이트 문자열을 base64 인코딩된 문자열로 반환 return fernet.encrypt(phone_number_bytes).decode('utf-8') def decrypt(encrypted_phone_number): """암호화된 핸드폰 번호를 복호화하는 함수""" # base64 인코딩된 문자열을 바이트 문자열로 변환 encrypted_phone_number_bytes = encrypted_phone_number.encode('utf-8') return fernet.decrypt(encrypted_phone_number_bytes).decode('utf-8')# models.py from .encrypt_utils import encrypt, decrypt from django.db.models import CharField class EncryptedCharField(CharField): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 암호화 처리 def get_prep_value(self, value): if not value: return None return encrypt(value) # 복호화 처리 def from_db_value(self, value, expression, connection): if value is None: return value return decrypt(value)암호화 할 수 있는 필드를 새로 만들어 주었다. (해당 필드를 전화번호로 지정해 주었다.)
class User(AbstractBaseUser): .... phone = EncryptedCharField('전화번호', max_length = 255, blank = True, null = True ) ....해당 에러 때문에 'latin-1' codec can't encode characters in position 55-56: ordinal not in range(256)
2일 동안 검색하고 무엇이 문제인지 stackoverflow에도 확인했지만, 도무지 해결이 되지 않았는데, 결과적으로 내 코드의 문제였다는 것을 깨닫고 하나하나 더 잘뜯어 봐야겠다는 생각을 바꾸게 하였다.
Ref.
[Python] Python과 cryptography를 통해 대칭키 암호화 하기!
Python에서는 다양한 방법을 통해 암호화 관련 알고리즘을 구현할 수 있습니다. 그 중 cryptography의 Fernet을 활용한 대칭키 암호화 알고리즘을 해보려합니다. 대칭키 암호화 방식 먼저 대칭키 암호
somjang.tistory.com
https://ddolcat.tistory.com/713
[Python] 파이썬 대칭키 암호화 알고리즘 cryptography 모듈 설치 및 사용방법 알아보기
파이썬에서 간단하게 문자열(텍스트)을 암호화 할 수 있는 방법에 대해 알아봅니다. cryptography는 대칭키를 사용하여 암호화 및 복호화를 하게 됩니다. 대칭키란 암호화 할 때와 복호화 할 때 동
ddolcat.tistory.com
- 제가 겪은 오류를 해결하기위해 검색하고 블로그에 작성한 글입니다. 부족한점이 많지만 틀린점이나 부족한점이 있다면 말씀해주시면 감사하겠습니다.
'공부 > 오류' 카테고리의 다른 글