🚀 학습 목표
- 인증, 인가에 대해 설명할 수 있다.
- 단방향 해쉬가 무엇인지 설명할 수 있다.
- salting & key stretching이 무엇인지 설명할 수 있다.
- Bcrypt와 JWT가 무엇인지 설명할 수 있다.
인증 (Authentication)
- 인증은 유저의 identification을 확인하는 절차
- 유저가 누구인지 확인하는 절차 -> 회원가입 / 로그인
- 사용자를 식별하기 위해 -> 사용자 추적
- 우리 서비스를 누가 스며 어떻게 사용하고 있는지 추적이 가능하도록 하기 위해서
인증에 필요한 것은 무엇일까?
- ID / Email / Password
- 가장 중요한 것은 Password
- 비밀번호 -> 법적으로 규정되어 있음
- 국가에서 권고하는 상용 암호화 알고리즘을 이용해 개인정보를 암호화하도록 법적으로 요구하고 있음
- 비밀번호는 암호화하여 저장함
비밀번호 어떻게 관리해야 하는가?
- 통신 시 개인 정보를 주고받을 때 SSL을 적용하여 암호화 (HTTPS) -> 암호화 할 수 있냐 없냐
암호화는 어떻게 할까요?
- 해쉬함수 : 빠른 자료 검색 / 데이터 위변조 체크를 위해 쓰인다
- 단방향 해쉬함수 : 복원 불가능 (원본 값에서 해쉬된 값을 움직임 -> 유추해낼 수 없음)
- 1234 해싱 했을 때 항상 같은 결과가 도출 (같은 알고리즘 사용 시) -> 해싱된 결과를 가지고 1234를 유추해낼 수 있음 -> 허점 존재
- 원본값을 유추해낼 수 없지만 해싱된 값(무엇을 입력했을 때 어떤 해시값이 나오는지는 알 수 있음 , 항상 같기 때문에) -> 전혀 암호화 되지 않고 유추 가능
- 허점을 해결하고자 salting / Key stretching 이라는 아이디어가 나옴
- 보안을 할 때는 유추할 시간을 최대한 길게 늘려주자
- 해시값의 노출 위험성 -> salting
- 해시값에 salting -> 다른 해시 값이 나옴 (원본 값에 + salt)
- salt값은 저장해 놓아야 함 (내가 어떤 솔트값이랑 저장해서 결과의 해시값이 나왔는지)
bycrpt
- bycrpt : salting / Key stretching 대표적 라이브러리
- 해쉬의 결과값 + 소금값 + 반복횟수 같이 보관
- 따로 저장해둘 필요가 없이 알아서 분리해서 저장함
- 알고리즘 / 소금값 / 해쉬 값 = 하나의 패스워드라고 생각하고 저장함
- bycrpt가 알아서 해쉬된 패스워드랑 맞는지 비교해줌
인가
- 해당 유저가 요구에 해당하는 권한이 있는지 확인하는 절차
- HTTP의 특징 (요청과 응답)
- stateless 성질 (저장하지 않는) -> 이전 로그인 기억하지 못함 -> 어떤 특정 로직을 개발해야 된다
- 해결하기 위해 -> 기억하기 해주자 -> JSON Web Token -> 헤더스에 특정 메타데이터(데이터를 설명할 수 있는)를 담아서 보냄 - JSON Web Token -> 로그인 성공했을 시 응답으로 토큰을 발급해줌 -> 발급한 토큰을 프론트에서 저장 -> 다른 인가가 필요한 api를 호출할 때 토큰을 담아서 보냄 -> 다시 로그인 할 필요없음 -> stateless 성질 해결됨
개인식별 + 자격요건 충족
JSON Web Token
헤더 (header)
헤더에는 토큰의 타입 + 해시알고리즘 정보 (BASE64 방식으로 인코딩해서 JWT의 가장 첫 부분에 기록된다)
인코딩 : 형태만 변환해준것
개인정보가 들어가면 안됨 -> 알고리즘 정보만 담음
내용 (playload)
만료시간을 나타내는 Registered Claim, 이미 등록된 키값들에 알맞은 value를 넣어주면 의도했던 대로 정보를 활용할 수 있음
공개용 정보 전달을 목적으로 하는 Public Claim,
클라이언트와 서버간 협의하에 사용하는 Private Claim
=> 위의 세가지 요소를 조합하여 작성한 뒤 BASE64 인코딩하여 두번째 요소에 위치
헤더 / 내용 : 암호화가 아닌 인코딩이다 , 개인정보를 넣어줄 수 없음, 개인정보는 아니지만 개인정보를 식별할 수 있는 PK 값을 넣어준다
서명 (signature)
우리 서버에서 발급한 토큰인지 확인하는 부분
JWT가 원본 그대로라는 것을 확인할 때 사용하는 부분
헤더와 내용을 헤더에 지정된 암호 알고리즘으로 암호화하여 전송함 (복호화 가능)
고유한 키값을 가지고 암호화하였기에 그대로 복호화 가능
-> 만약 값이 같다면 우리 서버가 발급한 토큰이라고 볼 수 있음
헤더 : 암호화 해야 될 알고리즘 정보 -> 인코딩 됨
내용 : DB PK값을 담아서 -> 인코딩
서명 : 정보를 담아서 암호화 -> 시크릿 키도 넣어서 암호화
스테이트리스 하기 때문에 -> 두번째 요청할 땐 기억 못하기에 첫번째 요청에서 발급된 토큰을 가지고 다음부터 계속 보내줌