JWT란?
JWT는 Json Web Token의 줄임말로, 클레임이라는 형태의 정보 조각들을 JSON 형태로 디지털 서명이나 암호화하여 데이터를 생성하는 표준이다. 즉, 보안이 필요한 정보를 안전하게 전달할 수 있는 토큰을 만드는 방법이다.
JWT Authentication은 이러한 JWT를 이용해서 사용자를 인증하는 방식을 말한다.
왜 JWT인가?
일단, 기본적으로 JWT는 보안 데이터 전달을 위해 사용하며, 주로 로그인 등의 사용자 인증을 위해 사용한다.
특히, 하나의 End Point가 아닌 Mobile/Web 등의 multiple endpoint 환경에서는 이러한 방식이 선호된다. 예를 들어, rest API를 사용하는 경우 이러한 방식을 사용하며, 구글 로그인 등 3rd Party에서 인증을 제공할 때 역시 JWT방식을 이용한다.
JWT의 장점은 사용자 인증에 필요한 모든 정보를 토큰 자체에 포함한다는 것이다. 이 때문에 사용자 정보를 따로 저장할 필요가 없다.
JWT인증과정
인증과정은 크게 2가지로, token을 발급받는 과정과 token을 이용해 인증받는 방식으로 나뉜다.
로그인을 할 때를 생각해보면,
1. 로그인을 하면 서버에서는 ID와 password를 바탕으로 토큰을 만들어 전달한다. 이 때, 해당 토큰을 생성하는 서버는 application server일 수도 있고, 3rd Party일 수도 있다.
2. 이후 클라이언트는 제한된 리소스를 요청할 때마다 이 토큰을 함께 전달하여 인증받는다.
JWT 토큰의 구조
JWT토큰은 헤더(Header), 페이로드(Payload), 시그니쳐(Signature)로 구성된다.
헤더(Header)에는 토큰의 타입과 디지털 signing을 위해 사용된 알고리즘을 명시한다.
페이로드(Payload)에는 전달한 Data를 저장한다.(Claim이라는 정보형태를 JSON방식으로 저장)
시그니쳐(Signature)는 헤더(Header)와 페이로드(Payload) 값을 base64로 인코딩한 값을 암호화한 값을 명시한다.(암호화를 할 때 SecretKey가 필요하다.)
->안전한 이유 : 만약 누군가 JWT토큰을 변조해서 전송한다면, 이 때 변조된 페이로드를 해싱한 값과 시그니쳐 값이 다르기 때문에 변조되었다는 것을 알 수 있다.
로그인 과정
0. 회원가입을 통해 ID와 비밀번호를 저장한다.
1. 로그인한다. -> 서버에서 JWT 토큰을 클라이언트에 전달한다.
2. 이후 제한된 리소스를 요청할 때, 가지고 있는 JWT토큰을 함께 전달하여 로그인 상태임을 인증한다.
스프링시큐리티에서 JWT
0. Form기반의 인증을 할 때와 마찬가지로 UserDetails와 UserDetailsService의 구현이 필요하다.
1. 회원가입 시 사용자ID, 인코딩한 PW, 그리고 roles를 db에 저장한다.
2. 로그인 시, (1)ID가 있는지 확인하고, (2)PW가 맞는지 확인하고, (3)토큰을 생성해서 클라이언트에 전달한다.
3. 제한된 리소스 요청이 토큰과 함께 오면, UsernamePasswordAuthenticationFilter라는 필터가 불리기 전에 사용될 Filter를 만든다.
해당 Filter는 (1)Header에서 Token을 추출하고, (2)해당 토큰이 유효한지 확인하고 (3)해당 토큰으로부터 Authentication객체를 만들고, (4)이를 Security Context에 저장한다.
4. 이 다음부터는 Spring Security가 알아서 해주는데, SecurityContext에 들어가있는 Authentication객체가 ProviderManager(AuthenticationManager의 구현체)의 authenticate메서드를 통해 인증여부에 따라 true, null 또는 exception을 반환한다.
구체적인 코드는 https://webfirewood.tistory.com/m/115?category=694472 해당 블로그에 정리가 잘 되어 있어 참고하면 좋을 듯하다.
'Spring' 카테고리의 다른 글
| 스프링(부트) - DTO와 Entity의 분리 (0) | 2020.08.17 |
|---|---|
| Spring - 의존성주입 방법의 비교(생성자 주입, Setter주입, field주입) (0) | 2020.06.11 |
| SpringSecurity - jdbc를 이용한 인증/권한 처리 (0) | 2020.05.12 |
| SpringSecurity - 서블릿 기반 구조 (0) | 2020.05.12 |
| Spring - ServletContext와 RootContext (0) | 2020.05.08 |