인증, 쿠키, 세션, JWT
Http 메시지를 보내는 것
헤더, 공백(헤더와 바디를 나누는 것), 바디
헤더 - 요청에 대한 정보가 들어감
바디 - 서버로 보내야할 데이터가 들어감
1. Session / Cookie 방식

순서는 요약하면 다음과 같습니다.
- 사용자가 로그인을 한다.
- 서버에서는 계정정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여하여 세션 저장소에 저장한 후, 이와 연결되는 세션ID를 발행하고, HTTP 헤더에 실어 사용자에게 돌려보낸다.
- 사용자는 서버에서 해당 세션ID를 받아 쿠키에 저장을 한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보냅니다. (쿠키에 세션ID를 넣어 헤더에 실어 서버에 보낸다.)
- 서버에서는 쿠키를 받아 세션 저장소에서 (세션ID를) 대조한 후 대응되는 정보를 가져옵니다.
- 인증이 완료되고 서버는 사용자에 맞는 데이터를 보내줍니다.
세션 쿠키 방식의 인증은 기본적으로 세션 저장소를 필요로 합니다(Redis를 많이 사용). 세션 저장소는 로그인을 했을 때 사용자의 정보를 저장하고 열쇠가 되는 세션ID값을 만듭니다. 그리고 HTTP 헤더에 실어 사용자에게 돌려보냅니다. 그러면 사용자는 쿠키로 보관하고 있다 인증이 필요한 요청에 쿠키(세션ID)를 넣어
보낼 것입니다. 웹 서버에서는 세션 저장소에서 쿠키(세션ID)를 받고 저장되어 있는 정보와 매칭시켜 인증을 완료합니다.
세션 - 서버에서 가지고 있는 정보
쿠키 - 사용자에게 발급된 세션을 열기위한 열쇠(세션ID)
###
(장점)
- 세션/쿠키 방식은 기본적으로 쿠키를 매개로 인증을 거칩니다. 여기서 쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠라고 보시면 됩니다. 따라서 쿠키가 담긴 HTTP 요청이 도중에 노출되더라도 쿠키 자체(세션 ID)는 유의미한 값을 갖고있지 않습니다(중요 정보는 서버 세션에) 이는 위의 계정정보를 담아 인증을 거치는 것보단 안전해 보입니다.
- 사용자 A는 1번, 사용자 B는 2번 이런식으로 고유의 ID값을 발급받게 됩니다. 그렇게 되면 서버에서는 쿠키 값을 받았을 때 일일이 회원정보를 확인할 필요 없이 바로 어떤 회원인지를 확인할 수 있어 서버의 자원에 접근하기 용이할 것입니다.
(단점)
- 장점 1에서 쿠키를 탈취당하더라도 안전할 수 있다고 언급했습니다. 그러나 문제가 하나 있습니다. 만일 A 사용자의 HTTP 요청을 B 사용자(해커)가 가로챘다면 그 안에 들어있는 쿠키도 충분히 훔칠 수 있습니다. 그리고 B 사용자는 그 훔친 쿠키를 이용해 HTTP 요청을 보내면 서버의 세션저장소에서는 A 사용자로 오인해 정보를 잘못 뿌려주게 되겠죠(세션 하이재킹 공격이라고 합니다)
-> 해결책
- HTTPS를 사용해 요청 자체를 탈취해도 안의 정보를 읽기 힘들게 한다. 2. 세션에 유효시간을 넣어준다.
- 서버에서 세션 저장소를 사용한다고 했습니다. 따라서 서버에서 추가적인 저장공간을 필요로 하게되고 자연스럽게 부하도 높아질 것입니다
2. JWT ( Json Web Token ) : 토큰 기반 인증 방식
토큰을 만들기 위해서는 크게 3가지, Header,Payload, Verify Signature가 필요합니다.
Header : 위 3가지 정보를 암호화할 방식(alg), 타입(type) 등이 들어갑니다.
Payload : 서버에서 보낼 데이터가 들어갑니다. 일반적으로 유저의 고유 ID값, 유효기간이 들어갑니다.
Verify Signature : Base64 방식으로 인코딩한 Header,payload 그리고 SECRET KEY를 더한 후 서명됩니다.
최종적인 결과 : Encoded Header + "." + Encoded Payload + "." + Verify Signature
Header, Payload는 인코딩될 뿐(16진수로 변경), 따로 암호화되지 않습니다. 따라서 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있습니다. 여기서 누구나 디코딩할 수 있다는 말은 Payload에는 유저의 중요한 정보(비밀번호)가 들어가면 쉽게 노출될 수 있다는 말이 됩니다.
하지만 Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없습니다.
A 사용자가 토큰을 조작하여 B 사용자의 데이터를 훔쳐보고 싶다고 가정하겠습니다. 그래서 payload에 있던 A의 ID를 B의 ID로 바꿔서 다시 인코딩한 후 토큰을 서버로 보냈습니다. 그러면 서버는 처음에 암호화된 Verify Signature를 검사하게 됩니다. 여기서 Payload는 B사용자의 정보가 들어가 있으나 Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주하게 됩니다. 여기서 A사용자는 SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없다는 걸 확인할 수 있습니다.

- 사용자가 로그인을 한다.
- 서버에서는 계정정보를 읽어 사용자를 확인 후, 사용자의 고유한 ID값을 부여한 후, 기타 정보와 함께 Payload에 넣습니다.
- JWT 토큰의 유효기간을 설정합니다.
- 암호화할 SECRET KEY를 이용해 ACCESS TOKEN을 발급합니다.
- 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냅니다.
- 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후, 조작 여부, 유효기간을 확인합니다.
- 검증이 완료된다면, Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옵니다.
세션/쿠키 방식과 가장 큰 차이점은 세션/쿠키는 세션 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보들이 넣는다는 점입니다. 물론 클라이언트 입장에서는 HTTP 헤더에 세션ID나 토큰을 실어서 보내준다는 점에서는 동일하나, 서버 측에서는 인증을 위해 암호화를 하냐, 별도의 저장소를 이용하냐는 차이가 발생합니다.
'개발일지 > 스프링' 카테고리의 다른 글
스프링 AOP란 (0) | 2022.05.07 |
---|---|
DI(의존성 주입) 방법 (0) | 2022.05.06 |
스프링 MVC 패턴 (0) | 2022.02.06 |
ORM 과 SQL (0) | 2022.02.06 |
스프링 IoC, DI, Bean 이란 (0) | 2022.01.30 |