Spring security를 이용하여 프로젝트에 보안 시스템을 구성할때 내가 JWT에 대한 전문지식이 부족한 것을 깨달았다. 그래서 포스팅을 해보며, JWT와 Spring security에 대해서 확실한 지식을 쌓고자 한다.
먼저, 우리는 사용자의 인증 및 인가를 하기 위해 세션 또는 토큰을 사용한다.
그 전에 인증과 인가의 차이점을 짚고 넘어가보자.
인증과 인가의 차이
비슷하지만 아예 다른 두 말.
인증 : 어떤 사실 또는 어떤 문서가 진짜인지 증명하는 과정을 가리키는 용어
인가 : 어떤 개체가 어떤 리소스에 접근할 수 있는지 또는 어떤 동작을 수행할 수 있는지를 검증하는 것, 즉 접근 권한을 얻는 일
쉽게 말하여, 인증은 로그인을 하는 과정이라고 생각한다. 네이버 메일에 로그인 하려고 할때, 네이버 시스템에서는 아이디와 패스워드를 요구한다. 우리가 알고있는 아이디, 패스워드를 입력하여 자신을 인증 할 수 있다.
인가는 야구를 보러가서 티켓을 확인하는 것을 말한다. 그 사람들은 우리가 우리인지에는 관심이 없다. 오직, 내가 티켓을 들고 있는지만 관심이 있다는 것이다. 우리가 야구티켓(토큰)을 가지고 있다면 야구경기(리소스)에 접근 할 수 있다는 것이다. 인가를 위해 우리는 토큰이라는 것을 보통 사용할 것인데, JWT도 토큰의 일종이다.
여기서 중요한 점은 인증 -> 인가 이지만, 인가 -> 인증 은 아니다!
세션 혹은 토큰
HTTP 프로토콜은 기본적으로 stateless 하다.
이 말은 HTTP 프로토콜은 통신을 기억하지 않는다는 것이다. 바로 직전의 통신도 기억하지 못하는 것이 HTTP 이다. 인증과 인가를 위해서는 어딘가에 기억을 해둘 무언가가 필요하다. 그래서 우리는 이를 위해 세션이나 토큰을 사용한다.
세션과 토큰에 대해서 자세하게 말하고 싶지만, 차이점만 간단히 알고 넘어가자.
세션은 서버측 데이터베이스에 저장되고, 토큰은 클라이언트 측에서 기억하고 있는다는 점이다.
세션이 토큰보다 안정성, 크기 면에서 유리하다.(크게 신경 쓰이는 거 까지는 아닌거 같음) 하지만, 대부분의 웹 시스템이 현재 토큰을 채택하고 있는 부분은 확장성 부분에서 토큰이 유리하기 때문이다. 서버 분산/클러스터 환경에서 세션을 사용한 인증을 채택하고 있다면, 우리는 다른 서비스를 이용할려고 들어가면, 해당 서비스가 다른 서버에서 운용되고 있다면, 우리는 한번더 로그인을 해야될 것이다. 하지만, 토큰은 클라이언트 측에서 해당 토큰을 저장하고 있기 때문에, 이러한 것이 문제가 될 필요가 없다.
(세션에서 이러한 문제점을 위해 sticky session이라는 것을 적용할 수 있다는데, 다음에 알아봐야겠다.)
JWT
정보를 비밀리에 전달하거나 인증할 때 주로 사용하는 토큰으로, Json객체를 이용함
웹 상에서 정보를 Json형태로 주고 받기 위해 표준규약에 따라 생성한 암호화된 토큰으로 복잡하고 읽을 수 없는 string 형태로 저장되어있다.
Jwt는 헤더, 내용, 서명 총 3개의 형태로 나뉘어져 있다.
- 헤더 (Header)
사용하는 암호화 알고리즘의 종류와 사용하는 토큰의 종류가 적혀져 있다.
- 정보 (Payload)
전달하려는 정보(사용자 id나 다른 데이터들, 이것들을 클레임이라고 부른다)가 들어있다.
payload에 있는 내용은 수정이 가능하여 더 많은 정보를 추가할 수 있다. 그러나 노출과 수정이 가능한 지점이기 때문에 인증이 필요한 최소한의 정보만을 담아야한다.
- 서명 (Signature)
헤더와 정보를 합친 후 발급해준 서버가 보유하고 있는 secret key로 암호화 시켜 토큰을 안전하게 관리해준다.
한가지 예를 들어보자면 토큰이 발급된 후 누군가가 Payload의 정보를 수정하면 Payload에는 다른 누군가가 조작된 정보가 들어가 있지만 Signatute에는 수정되기 전의 Payload 내용을 기반으로 이미 암호화 되어있는 결과가 저장되어 있기 때문에 조작되어있는 Payload와는 다른 결과값이 나온다. 우리는 이것을 보고 변조가 됐는지 안됐는지를 쉽게 파악할 수 있다.
jwt.io에서 우리는 쉽게 JWT를 생성 및 변환 할수도 있다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
JWT 프로세스
JWT는 접근에 관여하는 Access Token과, 재발급에 관여하는 Refresh Token 2개를 생성한다.
Access Token 만을 이용한 인증에는 취약한 문제점이 있다. 제 3자가 Access Token을 탈취한다면 보안에 취약하다는 점이다. Access Token은 서버에 저장되지 않고, 토큰 자체로 인증을 진행하기 때문에 토큰을 탈취당한다면 토큰이 만료되기 전까지 토큰을 획득한 아무나 사용이 가능해진다.
따라서, 우리는 Refresh Token을 도입해 만료시간을 짧게 가져간다. 8~13 과정까지가 Refresh Token을 이용한 토큰 재발급 과정이다.
클레임 기반 토큰
JWT는 대표적인 클레임 기반 토큰이다.
여기서 클레임이란 사용자에 대한 프로퍼티나 속성을 말한다.
기존에 주로 사용하던 일반 토큰 기반 인증은 토큰을 검증할 때 필요한 관련 정보들을 서버에 저장해두고 있었기 때문에 항상 DB에 접근해야만 했었다.
하지만, 클레임 토큰 기반 인증은 사용자 인증에 필요한 모든 정보를 토큰에 갖고 있기 때문에 별도의 인증 저장소가 필요 없다. 분산 마이크로 서비스 환경에서 중앙 집중식 인증 서버와 데이터베이스에 의존하지 않는 쉬운 인증을 제공하여 일반 토큰 기반 인증에 비해 편리하다고 말할 수 있다.
'Spring' 카테고리의 다른 글
[Spring JPA] JPA 하이버네이트에서의 프록시 (0) | 2024.07.21 |
---|---|
[Spring JPA] JPA에서 OSIV와 커맨드,쿼리의 분리 (2) | 2024.07.18 |
[Spring] 컬렉션 fetch join(페치 조인) 을 이용한 성능 최적화 및 페이징 (0) | 2024.07.15 |
[Spring JPA] JPA 에서 fetch join(페치 조인)이란 (0) | 2024.07.14 |
컴포넌트 스캔 (0) | 2023.08.05 |