-
JsonWebToken -Jwt란?JsonWebToken 2021. 2. 16. 15:34
현재 개인적으로 만드는 토이프로젝트에 로그인 기능을 제작할 때,
평소에는 스프링 시큐리티의 폼 로그인으로만 사용했지만 프론트엔드를 Vue를 사용하다보니
개인적으로 연결도 어렵고,, 안되는게 참 많았는데 그렇기에 이렇게된거 아예 토큰기반 인증으로
만들어보기로 했고, Jwt를 알아보는 계기가 되었습니다.
먼저 Jwt의 설명과 동작 방식을 설명하기 전에, 먼저 알아두면 좋을 것들을 작성하겠습니다.
웹/앱 어플리케이션에서 인증의 필요성
사용자 기준에서의 인증은 로그인과 같이 사용자의 도입부분을 가리킬텐데요,
이를 서버 기준에서 본다면 인증이란 모든 API 요청에 대해 접근한 사용자가 올바른 사용자인지를
확인하는 작업 그리고 클라이언트 기준으로 본다면 서버가 사용자를 판단할 근거를 넘겨주어야 한다고
저는 생각합니다.
사용자 A, 사용자 B가 존재할 때 각 사용자는 요청하는 정보도 다를것이며, 보관하고 있는 정보들도
다를 것입니다. 그렇기에 서버에서는 사용자 A와 사용자 B가 서로 다른 사용자임을 인식하고 요청이
들어왔을 때 해당 요청이 어떤 사용자의 요청인지를 파악해, 해당 사용자에게 올바른 정보를 전달하며
서로의 정보가 유출되지 않도록 하게됩니다.
인증 방식
1. HTTP 요청 헤더에 사용자의 계정정보를 넣어 인증하는 방식
API를 요청할 때마다 사용자의 패스워드를 비롯한 계정 정보를 넘겨주는 방식입니다.
얼핏 보기만 해도 보안에 아주 취약하며, 비효율적이란 것을 알 수 있는데요,
그렇기에 거의 사용되지 ( 사용하면 안되는 )않는 방식입니다.
장점
- 인증 테스트할 때 빠르고 편하게 테스트 할 수 있다.
단점
- 보안에 매우 취약하다.
- 서버에서 계정정보를 받았을 때 요청마다 그 계정정보를 통한 사용자 인증을 시도해 효율적이지 못하다.
2. 서버기반 인증
1번의 인증 방식은 보안에 매우 취약하게, 이를 보완하는 방식이 서버기반 인증인 Session과 Cookie입니다.
동작 순서는 사진과 첨부 설명으로 보시겠습니다.
사진 출처 : https://tansfil.tistory.com/58 동작 순서에 대해 설명하자면,
1 - 사용자 로그인
2 - 서버에서 1번에서 넘어온 데이터를 통해 DB의 사용자 정보와 일치하는지 확인
3 - 2번의 결과가 일치한다면 사용자의 고유 값(ID 등 )을 세션 저장소에 저장
4 - 3번에서 저장된 값과 연결되는 세션 ID를 발급
5 - 사용자에게 데이터와 Session Id를 포함해 응답, 사용자는 Session Id를 쿠키에 저장
6 - 앞으로의 요청은 5에서 저장한 쿠키를 포함해 요청.
7,8 - 6에서 같이 전송된 쿠키를 받아 세션 저장소에서 대조 한 뒤 정보를 가져옴
9 - 사용자에게 응답
장점
- 세션 저장소에 저장된 유저 정보를 얻기 위한 수단?열쇠?인 쿠키를 통해 인증을 거치는데,
쿠키는 1번 인증방식과 달리 유의미한 정보가 들어있지 않아 보안에 더 유리하다.
- 쿠키를 통해 요청하게 되면, 쿠키로 세션 저장소에 접근해 회원 정보를 알 수 있기에 더 효율이다.
단점
- 하이재킹 공격의 위험성이 존재한다
하이재킹이란 쉽게 예를 들어
사용자 A가 데이터 요청을 했을 때 같이 담아 보낸 쿠키를 사용자 B가 탈취했을 때,
사용자 B가 탈취한 쿠키로 요청했을 때 서버는 이 사용자 B의 요청을 사용자 A의 요청으로 오인하여
사용자 A의 정보를 전송하게 되는 것 입니다.
- 서버에서 따로 세션 저장소를 사용하기에, 추가적인 저장공간을 확보해야 하고 그에 따라 부하가 늘어난다.
3.토큰기반 인증 중 Jwt
이제야 Jwt에 대한 내용이 등장하게 되었네요.
JsonWebToken의 약자로 인증에 필요한 정보들을 암호화 시킨 토큰을 의미합니다.
2번 서버기반 인증의 쿠키와 같이 사용자는 Jwt로 발급한 토큰을 HTTP 헤더에 담아 서버에 요청합니다.
먼저 Jwt에 대한 간단한 정보를 적어보자면,
토큰을 생성하기 위해는 크게 3가지 요소가 필요합니다. ( Header, Payload, Signature )
Header - 위의 3가지 정보들을 암호화 할 알고리즘,방식인 alg, 타입 type을 설정.
Payload - 서버가 전송할 데이터가 들어감 일반적으로 사용자의 고유 값, 만료기간 등
Signature - Base64 방식으로 Header, Payload를 사용자가 설정한 SecretKey(비밀키)를 더한 뒤 인코딩함.
생성된 토큰은 Encoded Header . Encoded Payload . Signature로 구성되어 나타납니다.
출처 : jwt.io 여기서 Header와 Payload는 그냥 인코딩만 된 상태이기에 누구나 접근해 디코딩하여 값을 확인할 수 있습니다.
그렇기에 Payload에 비밀번호 등 중요한 정보를 넣지 않고 생성하셔야 합니다.
그렇지만, Signature는 설정된 SecreyKey를 모르는 상태에서는 복호화 할 수 없습니다.
동작 순서는 사진과 첨부설명으로 보시겠습니다.
출처 : https://tansfil.tistory.com/58 동작 순서에 대해 설명하자면,
1- 사용자 로그인
2 - 서버에서 1번에서 넘어온 데이터를 통해 DB의 사용자 정보와 일치하는지 확인
3- 2번에서 사용자 검증을 마쳤다면, Payload에 정보를 담아 생성
4- 3번에서 생성된 Access Token을 사용자에게 전달
5- 사용자는 요청할 때 4번에서 받아온 Access Token을 헤더에 담아 요청
6- 서버에서는 5번에서 전송된 Access Token을 SecretKey를 통해 Signature복호화 한 뒤 검증
7- 6번에서 검증에 성공했다면 데이터를 사용자에게 전송.
서버기반 인증인 Session, Cookie과 같이 HTTP 헤더에 인증에 필요한 매체를 전달하는 것은 흡사하나,
가장 큰 차이점은 세션과 쿠키를 사용한다면 세션 저장소에 사용자의 정보를 저장하고
토큰을 사용한다면 토큰 안에 사용자의 정보를 저장하는 것이라고 생각합니다 .
장점
- 별도의 저장소가 필요없어 부하가 줄어들게 되며 Stateless상태에 도움이된다.
Stateless란 ?
간단하게 말하자면, 별도의 저장소를 사용하지 않으며 상태를 저장하지 않는 것을 뜻함.
- 이로인해 유지보수가 조금 더 수월하며, 확장성 또한 뛰어나다
단점
- 이미 발급된 Access Token에 대해 강제성을 발휘할 수 없다.
이는 Access Token이 탈취되었을 때 유효기간이 만료되어 자연스럽게 소멸될 때까지
계속해 사용이 가능하기에 탈취된 토큰이 악의적으로 사용될 수 있음을 알 수 있다.해결책
- 발급되는 Access Token의 유효기간을 짧게 설정하고, Refresh Token이라는 토큰을 검증하는 토큰을
별도로 생성해 사용한다 .
개인적인 의견 - Access Token의 탈취 우려와, 이에 대한 해결책으로 Refresh Token을 사용한다는 것은 알겠는데
찾아보면 Refresh Token은 안전한 저장소에 저장한다고 하는데, 이를 어디다가 저장할지도 잘 모르겠고,,
클라이언트가 Access와 Refresh Token을 둘 다 가지고 있으면 Access Token이 탈취될 때 Refresh Token 또한 같이 탈취되는 것이 아닌가?? 라는 생각이 매우 드네요.. 그래서 적용할 땐 더 생각해보고 써야할 것 같습니다.
- 사용자의 정보를 담는 Payload에 담을 정보가 제한적이다. ( 장점,,이자 단점? 이라고 생각한다 )
이론적으로 알아보았고 다음에는 Refresh Token에 대한 더 자세한 정보와 직접 Spring Boot를 이용해 적용하는 포스팅을 작성해 보겠습니다.
'JsonWebToken' 카테고리의 다른 글
JsonWebToken - Access Token과 Refresh Token (0) 2021.02.16