[Spring] 인증 방식(세션과 JWT)
인증(Authentication)
유저인지 "인증" 하는 것은 해당 유저가 진짜 그 유저인지 확인하는 행위
인가(Authorization)
해당 유저가 특정 리소스에 접근이 가능한지 허가를 확인하는 개념
웹 애플리케이션 인증의 특수성
일반적으로 서버-클라이언트 구조로 되어있고, 실제로 이 두가지 요소는 아주 멀리 떨어져 있습니다.
그리고 HTTP라는 프로토콜을 이용하여 통신하는데, 그 통신은 비연결성(Connectionless), 무상태(Stateless)로 이루어집니다.
- 비연결성(Connectionless)
서버와 클라이언트가 연결되어 있지 않다는 것 입니다.
만약 서버와 클라이언트가 실제로 계속 연결되어 있다면 서버의 비용이 기하급수적으로 늘어나기 때문입니다.
그래서 실제로 서버는 하나의 요청에 하나의 응답을 보내고 연결을 끊어버립니다. - 무상태(Stateless)
서버가 클라이언트의 상태를 저장하지 않는다는 것 입니다.
만약 서버가 클라이언트의 상태를 저장하게 된다면 서버의 비용이 증가하기 때문입니다.
서버는 클라이언트가 직전에 혹은 그 전에 어떠한 요청을 보냈는지 관심도 없고 전혀 알지 못합니다.
하지만 애플리케이션을 사용하다보면 클라이언트의 상태를 저장할 필요가 있습니다. 예를 들어, 로그인을 한 번 하게되면 일정 시간 동안은 로그인을 하지 않더라도 지속해서 로그인 상태가 유지되는 경우가 있습니다.
과연 어떻게 비연결성, 무상태 프로토콜에서 "유저가 인증되었다" 라는 정보를 유지시킬 수 있을까요?
쿠키-세션 방식의 인증
서버가 '특정 유저가 로그인 되었다'는 상태를 저장하는 방식입니다.
인증과 관련된 아주 약간의 정보만 서버가 가지고 있게 되고 유저의 인증과 관련된 최소한의 정보는 저장해서 로그인을 유지시킵니다.
1. 사용자가 로그인 요청을 보냅니다.
2. 서버는 DB의 유저 테이블을 뒤져서 아이디 비밀번호를 대조합니다.
3. 실제 유저테이블의 정보와 일치한다면 인증을 통과한 것으로 보고 "세션 저장소"에 해당 유저가 로그인 되었다는 정보를 넣습니다.
4. 세션 저장소에서는 유저의 정보와는 관련 없는 난수인 session-id를 발급합니다.
5. 서버는 로그인 요청의 응답으로 session-id를 응답합니다.
6. 클라이언트는 그 session-id를 쿠키라는 저장소에 보관하고 앞으로의 요청마다 세션 아이디를 같이 보냅니다.(주로 HTTP header에 담아서 보냅니다.)
7. 클라이언트의 요청에서 쿠키를 발견했다면 서버는 세션 저장소에서 쿠키를 검증합니다.
8. 만약 유저정보를 받아왔다면 이 사용자는 로그인이 되어있는 사용자 입니다.
9. 이후에는 로그인 된 유저에 따른 응답을 보냅니다.
JWT 기반 인증
JWT(Json Web Token)란 인증에 필요한 정보들을 암호화시킨 토큰을 의미합니다. JWT 기반 인증은 쿠키/세션 방식과 유사하게 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별합니다.
1. 사용자가 로그인 요청을 보냅니다.
2. 서버는 DB의 유저 테이블을 뒤져서 아이디 비밀번호를 대조합니다.
3. 실제 유저테이블의 정보와 일치한다면 인증을 통과한 것으로 보고 유저의 정보를 JWT로 암호화해서 내보냅니다.
4. 서버는 로그인 요청의 응답으로 JWT 토큰을 내어줍니다.
5. 클라이언트는 그 토큰을 저장소에 보관하고 앞으로의 요청마다 토큰을 같이 보냅니다.
6. 클라이언트의 요청에서 토큰을 발견했다면 서버는 토큰을 검증합니다.
7. 이후에는 로그인 된 유저에 따른 응답을 내어줍니다.