앞서서 인증 인가에 대한 개념을 할짝! 했으니 지금은 직접 키보드 뚜드리면서👨💻 몸으로 익히는 TIME을 가져봐야해요


실습을 위한 가상환경
python venv 혹은 conda env로 가상환경을 만들게요.
bcrypt pyjwt 요 두개를 pip로 다운받습니다.
pip install bcrypt pyjwt
설치가 완료되었다면 Ipython을 실행시키고 'bcrypt'를 임포트할게요.
그리고 비밀번호를 해쉬해주는 hashpwd() 함수를 사용하고 rainbow table attack을 막기위해서 salt값을 추가하도록 할게요.
아래 형식의 메소드를 구현해줘야!! -> hash🎠가 만들어져요.
bcrypt.hashpw( 바이트값, bcrypt.gensalt() )

위 내용 1~4번 더 첨언해볼게요.
b붙은건 해당 문자열을 byte로 만들어줘요.파이썬에서 문자열을 바이트로 만드는 방법은 아래와 같이 있어요.
추가 자료 - DelfStack - Convert String to Bytes in Python
b'문자열'키워드👓'문자열'.encode('utf-8')👓>>> byte = b'1234'
>>> print(type(byte))
<class 'bytes'>
>>>
>>> byte2 = '1234'.encode('utf-8')
>>> print(type(byte2))
<class 'bytes'>
왜?! byte값이 아닌 인트라서!
encode()를 사용하여 -> byte 타입으로 바꿀수 있어요👓byte -> 문자열로 바꾸려면 'byte'.decode('utf-8')해주면 되겠주?👓
랜덤한 바이트 값들이 계속 나오는걸 확인 할 수 있어요.
>>> bcrypt.gensalt()
b'$2b$12$4utpZCeHmvvIb5QiTTalCO'
>>> bcrypt.gensalt()
b'$2b$12$UENnkg4C.26rJJBZVSx.h.'
>>> bcrypt.gensalt()
b'$2b$12$bSZ8oI3gFA1aGeDxjITcfO'
>>> bcrypt.gensalt()
b'$2b$12$g8l200cGq0zK2ukvD7TDHu'
>>> bcrypt.gensalt()
b'$2b$12$XH8kdj8F8IHeXyGmoxAoDe'
>>> bcrypt.gensalt()
b'$2b$12$cHvrW8GdC9p6VE0zJzlRge'
>>> bcrypt.gensalt()
b'$2b$12$XzJRkFWF5knlwIvDhiXxL.'
>>> bcrypt.gensalt()
b'$2b$12$lR9Y04quIsOko.Hwcf13Tu'
아래 1번에서 gensalt()로 만든 salt값이 hashpwd()의 2번째 인자에 둬서 결국 hash_pwd변수의 값 앞부분에 위치한걸 확인 할수 있조?!

checkpw() 말 그대로 값을 비교하여 True, False를 반환하는데요. 이때 함수의 인자로는 바이트가 들어갈까요? 아니면 문자열일까요?
2번째줄에 password가 바이트라는거 확인! 그렇다면 7번째줄의 메서드에도 정황상 같은 데이터 타입을 비교할 거라는 예감 오나요?
네! 하지만 해쉬된 바이트로 bycrpt.hashpw() 값 한번 보안처리된 바이트 값이조?
즉!
checkpw(
그냥바이트값,해쉬된 바이트값)
이라는 말인거조!
1 >>> import bcrypt
2 >>> password = b"super secret password"
3
4 >>> hashed = bcrypt.hashpw(password, bcrypt.gensalt(14))
5
6
7 >>> if bcrypt.checkpw(password, hashed):
8 ... print("It Matches!")
9 ... else:
10 ... print("It Does not Match :(")
11
위에서 본 bcrypt는 단방향이에요.
즉, 복호화가 불가능에 가깝지만, 이제 살펴볼 JWT는 Jason Web Token을 복호화하면 Payload에 암호화하여 담긴 정보를 확인할 수 있어서 사용자가 로그인하면 백엔드 서버가 JWT 토큰을 frontend에 발행하게 되고 프런트앤드는 API를 요청시 request header의 Authorization 키에 access_token을 넣어서 보내면 백엔드 서버는 이 access_token에 담겨있는 header! payload signiture를 확인해서 인가 방법을 제공합니다.
즉, HTTP의 특성인
Stateless로 인하여 이전 사용자의 로그인을 유무를 알수 없지만 하지만 로그인시에발행한 JWT 토큰 정보를 근거로 백엔드 서버에서는 이 토큰 정보를 해석하는decorator를 만들어서 인가가 필요한endpoint들을 사용할 수 있어요.
jwt.encode()
딕셔너리 객체를 넣어줍니다. SECRET_KEY인데요. SECRET_KEY를 끌어다가 사용해요.주의1
jwt.encode(1번째, 2번째, algorithm='HS256')
jwt.decode(1번째, 2번째, algorithms='HS256')
별표 백만개!!!(오류 잡아낸다고 힘들었어요.)😥😣
- encode()는 algorithm이 단수형!
- decode()는 algorithms이 복수형!
주의2
4번째 앞에 b키워드가 없다?
그건 jwt 1.7 -> 2.0 넘어가면서 byte->str으로 타입이 변경되었기 때문에 그래요.
1 >>> import jwt
2 >>> encoded = jwt.encode({'user-id': 5}, "secret", algorithm="HS256")
3 >>> print(encoded)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U
4 >>> type(encoded_jwt)
<class 'str'>
5 >>> jwt.decode(encoded, "secret", algorithms=["HS256"])
{'user-id': 5}