: 아이디와 비밀번호(회원가입), 로그인의 과정을 통해 회원을 식별하는 것
데이터베이스에 저장 시 개인정보를 해싱하여 복원할 수 없도록 함.
통신 시 개인정보를 주고받을 때 SSL을 적용하여 암호화(HTTPS)
SSL : 사이트 주소바 왼쪽의 자물쇠로 잠겨있는 것으로 확인할 수 있음.
✅ SSL?
: 보안 소켓 계층(Secure Sockets Layer, SSL)
웹사이트와 브라우저(혹은, 두 서버) 사이에 전송된 데이터를 암호화하여 인터넷 연결을 보안을 유지하는 표준 기술.
단방향 해쉬(one-way-hash-function)란?
: 컴퓨터 자료구조중 하나로 빨리 검색하고 찾기 위해서 만들어낸 함수이다.
input - output이 한개씩 있다. 하나의 값이 들어가면 한개가 나온다.
단방향 해시 함수는 원본 메시지를 변환하여 암호화된 메시지인 다이제스트(digest)
를 생성한다. 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없기에 단방향성을 띄고 있다.
자료구조에서 빠른 자료의 검색, 데이터의 위변조 체크를 위해 쓰지만 복원이 불가능한 단방향 해쉬함수는 암호학적 용도로 사용한다.
ex) MD5,SHA-1,SHA-256
but!!
결과만 봐서는 당장 식별이 불가능해보이나, 다시 해싱하면 같은 결과가 나오는 단점이 있다.
: 해쉬값이 해킹에 쉽게 노출되어 salting이라는 개념이 생겨남
입력한 비밀번호와 임의로 생성한 문자열을 합쳐서 해싱해서 해시값을 저장하는 방법
1) bcrypt의 암호화 방법
: str 데이터가 아닌 Bytes 데이터를 암호화한다!
password = '2345'
#패스워드를 utf-8로 bcrypt하고 salting 한다.
hashed_password= bcrypt.hashpw(password.encode('utf-8',bcrypt.gensalt()))
print(hashed_password) #암호화된 값 출력
type(hashed_password) #'byte'
# 비밀번호 확인하기.
new_password = '2345'
bcrypt.checkpw(new_password.encode('utf-8'),hashed_password)
# checkpw를 통해 인코딩된 새로운 비밀번호와 hashed_password가 일치하는지 검증한다
✅ bcrypt.hashpw (사전 정의한 비밀번호. encode('utf-8',bcrypt.gensalt()))
: 정의해 둔 비밀번호를 utf-8 형태로 encode화시킨다. gensalt
=> salting 작업을 해준다!
✅ bcrypt.checkpw(비교할 비밀번호 1,비교할 비밀번호 2)
: encoding한 값과 원래 값이 같은가?
login하기 위해 입력한 값과 암호화된 비밀번호가 같은가? 비교하기 위해 사용해준다.
: 유저가 로그인에 성공한 후, access token
이라는 암호화된 유저 정보를 첨부해 request를 보낸다. access token
을 생성하는 널리 사용되는 기술이 JWT!
.
을 구분자로 [ header.payload.signature ] 로 구성되어 있다.1) header에는 어떤 정보가 들어가는가?
2) Payload (내용)
3) Signature: 서명
jwt가 원본 그대로라는 것을 확인할 때 사용하는 부분이다.
Signiture는 BASE64URL 인코드 된 header와 payloda 그리고 jwt secret 별도 생성을 통해 헤더에 지정된 암호 알고리즘을 암호화하여 전송한다. (복호화 가능)
프론트엔드가 jwt를 백엔드 api서버로 전송하면 서버에서는 전송받은 jwt의 서명부분을 복호화여 서버에서 생성한 jwt가 맞는지 확인한다.
계약서의 위변조를 막기 위해 서로 사인하는 것과 같은 개념.
header와 payload에는 개인정보를 적으면 보이기 때문에 절대 안됨!
jwt의 결과물은 pyjwt ver이 1.7이면 bytes. 2.0이상이면 str로 출력된다.
#토큰 만들기
SECRET = '랜덤한 조합의 키가 등장!'
access_token = jwt.encode({'id':1}, SECRET, algorithm = 'HS526')
# 인증을 위한 매개체를 만들기 위해 jwt.encode를 실행한다. id값 1번의, 랜덤 비밀번호를, 알고리즘을 활용해서.
print(access_token) #암호화 된 값 등장
#토큰 발행 결과 확인하기
header = jwt.decode(access_token, SECRET, algorithm = 'HS256')
# 헤더에 있는 access_token의 값을 decode한다. SECRET 비밀번호와 알고리즘을 활용해서
print(header) # => {'id' :1} 출력
✅ 토큰을 만들기 위해 특정 아이디를 encode한다.
✅ 로그인이 성공하면, 이 토큰을 프론트엔드 엔지니어에게 전달하고, 로그인 성공 시 발행 토큰을 전달해준다. 인증을 통과한 사용자만 접근하려면 토큰을 다시 받아 우리의 토큰이 맞는지 확인한다!
: token = jwt.encode (data, secret, algorithm)
✅ 인증하는 코드는 엔드포인터에 데코레이터를 구현해야하며, user app에 utils.py를 만들어 작성해준다.
⭐️ 유저 로그인 - access token - 복호화 과정⭐️
#유저의 로그인 시도
POST /auth HTTP/1.1
Host: localhost:5000
Content-Type: application/json
{
"username": "joe",
"password": "pass"
}
# 정상 로그인. access_token 발급
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDQ0OTE3NjQwLCJuYmYiOjE0NDQ5MTc2NDAsImV4cCI6MTQ0NDkxNzk0MH0.KPmI6WSjRjlpzecPvs3q_T3cJQvAgJvaQAPtk1abC_E"
}
#복호화 결과값
{
user_id = 1
}
- QUIZ TIME -
✅ 양방향 해쉬 : 원본을 확인해야 하는 정보에 사용함
ex) 주민번호 : 복호화하여 집어넣고 식별과정 시 꺼내서 복호화해서 확인
✅ 토큰을 타인이 뺏어서 쓰는 것을 방지하기 위해서는?
: ip 정보를 같이 저장하거나, 추가 검증과정을 하나 더 거치거나, 하는 등의 방식이 있다. 이러한 방식들도 공부해보면 좋다!
✅ 데이터베이스에는 암호화된 bcrypt 형태로 저장된다.
✅ salt값은 일정하지 않고 랜덤하다. (길이,값)
✅ password의 charfield값은 넉넉하게 주어야한다.
key-stretching 이후 변환된 값의 길이가 최대 길이를 넘어가도 오류가 발생함