서론.
해당 프로젝트에서는 오로지
카카오 소셜 로그인
만 사용한다. ( ID/PW 사용안함! )
이전 포스팅✅에서는 엑세스 토큰을 이용해 카카오 서버에서 사용자 정보를 받아오고 그것을 DB에 저장하는 법까지 알아보았다. 이어서 JWT를 발급해 프론트 측에 넘기기 전에, 필요한 지식들에 대해 알아보려고 한다.
기본 의존성 :
Spring Web
Spring boot DevTools
Lombok
Spring Security
MySQL Driver
spring Data JPA
추가한 의존성 :
jackson-databind
jackson-datatype-jsr310
java-jwt
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.(공식 홈페이지)
요약하자면, JWT는 Json 형식
으로 되어있고, 디지털 서명
이 되어 있다는 것이다. 그리고 서명 방식에는 HMAC
, RSA
등 여러 가지가 있다고 한다. 나는 위 방식 중에 HMAC
을 사용할 예정이다.
JWT 는 Header
Payload
Signature
각 세 부분으로 나뉜다. 아래 이미지를 살펴보자.
JWT 가 최종적으로 띄는 형태는 왼쪽의 Encoded 부분이다. 위에서 말한 세 부분은 각각 base64
라는 통상적인 방식으로 인코딩된다. 또한 세 부분을 나누는 구분점 .
이 있다.
Header
: Signature
를 암호화한 알고리즘에 대한 정보, 해당 토큰의 타입 정보가 들어간다.Payload
: Claim
을 포함하는 부분이다. 클레임에는 등록된 클레임
과 개인 클레임
이 있다.등록된 클레임
: iss
(발행자), exp
(만료 시간), sub
(제목), aud
(청중) 등이 있지만 필수 요소는 아니다.개인 클레임
: 당사자 간에 정보를 공유하기 위해 생성된 맞춤 클레임이다. 우리는 이 개인 클레임에 사용자를 식별할 수 있는 id
값을 넣을 것이다.base64
방식은 복호화가 가능하기 때문에 누구에게나 노출될 수 있다.Signature
: 서명을 하는 방식은 간단하다. 앞서 만든 Header
Payload
(각각 base64
로 인코딩 된 상태) 에 자신의 Secret Key
를 더해 Header
에서 언급했던 방식으로 해싱을 한다. 그리고 그 값을 또 다시 base64
로 인코딩하면 된다. Secret Key
는 어디에도 노출되면 안된다.😅 토큰의 유효성을 체크할 핵심 키이기 때문에 조심히 다뤄야 한다.JWT는 사용자의 민감한 정보들을 전달하는 것 보다는 서명된 토큰 자체에 중점을 둔다. 토큰에 서명을 한 사람이 맞다면 가지고 있던 비밀 키로 복호화 할 수 있을 것이고, 그렇지 않다면 그건 위조되었거나 유효하지 않은 토큰이므로 서버로의 접근을 제한할 수 있다.
JWT 를 설명하다가 갑자기
Security Filter
로 이야기가 튀어서 당황스러울 수 있다. 하지만 이Filter
에 대한 이해가 전혀 없다면, 토큰을 무사히 발행해도 유효성 체크를 하기가 어려울 수 있다.
나는 이미 시행착오를 겪어보았기 때문에😭😭 여기서 간단히 짚고 넘어가는 것을 추천한다.
기본적으로 DispatcherServlet(FrontController)이 요청을 받기 이전에 Filter
를 거쳐가게 되어 있다. 즉, api를 작성한 Controller 의 로직이 실행되기 이전에 필터가 동작하는 것이다. 그 중에서도 Security Filter
가 가장 우선적으로 실행된다.Security Filter
의 구성과 동작 순서는 아래 이미지와 같다.
이 중에 꼭 알아둬야할 필터는 UsernamePasswordAuthenticationFilter 이다.
Security Config 에 .formlogin()
설정을 해본 적이 있을 것이다. 이 필터는 폼 로그인을 할 때 username
password
를 이용해 인증을 진행해주는 필터이다.
이 필터에서 UserDetails
UserDetailsService
가 사용된다. 정상적으로 인증이 완료되면 Authentication
에 회원 정보를 담은 채로 시큐리티 세션을 생성한다.
아마 컨트롤러에서 이때 생성된 세션을 불러와 회원 정보를 얻어 본 적이 있을것이다.(Principal 객체)
도움 받은 영상 :
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9
마치며.
하지만 이 프로젝트에서는 폼 로그인을 사용하지 않을 뿐더러 JWT 로 사용자 인증을 할 것이기 때문에 위의 필터가 사용되지 않는다. 그러므로
Authentication
이 만들어 지지 않는다.
이러한 문제로인해 인증된 사용자의 정보를 불러올 다른 방법을 강구해야한다. 이는 이후의 포스팅에서 다룰 예정이다. 많관부많관부~🥳💖