ABOUT ME

Today
Yesterday
Total
  • JWT를 이용한 인증
    java 2021. 4. 16. 13:42

    배경

    진행하는 프로젝트는 인증, 인가를 위해 Session-Cookie방식을 사용하고 있다. 인증 프로세스를 통과한 사용자에게 인증된 쿠키를 응답헤더에 포함하고 그 쿠키를 key값으로 사용자 정보를 세션 형태로 저장한다. 이후 인증된 사용자에게 제공하는 api서비스는 전부 쿠키의 key값에 대한 value가 있는지 확인함으로써 인증을 시도한다.

     

    새로운 마이크로 서비스를 공부하면서 강의 내용은 인증 인가를 위해 JWT를 사용했다. 사실 JWT방식은 많이 들어보기도 했고 현대 아키텍처에서 자주 쓰인다고도 한다. 이번 기회에 명확하게 그 방법을 알아보자.

     

    Session-Cookie와 JWT의 차이점

    두 방법 모두 HTTP의 stateless를 극복하기 위해 헤더에 값을 저장한다. 다만, Session-Cookie는 헤더에 저장하는 값이 단지 세션 정보를 찾기 위한 key값이다. 반면, JWT의 헤더에 포함된 토큰은 사용자 정보를 담고 있다. 즉, JWT를 이용하면 서버 측에서 따로 세션을 저장하기 위한 메모리를 마련할 필요가 없다.

     

    JWT인증 아키텍처

    1) 클라이언트(Browser)는 인증을 위해 로그인 정보와 함께 인증을 요청한다

    2) 서버는 사용자가 보낸 인증정보를 확인한 후 유효하다면 JWT토큰을 발급해준다.

    3) 사용자는 서버가 전달한 토큰을 앞으로의 요청 헤더에 포함한다.

     

    JWT토큰 생성과정

    토큰을 생성하기 위한 필수 정보 2가지가 있다.

    1) 사용할 알고리즘 및 알고리즘에 사용할 서버만 아는(중요) 비밀키

    2) 사용자 정보

     

    서버는 비밀키를 이용해 발급한 토큰의 유효성을 검증할 수 있다.

     

    Custom Filter를 이용한 JWT인증 구현

    Custom Filter를 등록해 JWT인증을 구현해 보자.

     

    jwt 토큰을 생성하고 유효성을 검증하기 위한 라이브러리 의존성을 추가하자.

    (implementation으로 해야 test에도 사용할 수 있다)

     

    초간단 인증을 구현하기 위한 데이터베이스로 JPA와 h2를 사용했다. 여기서 중요한 건 마지막의 token의 valid_time과 secret_key이고 특히나 secret_key는 절대 노출되어선 안 될 정보다.(너무 짧으면 인코딩 시 오류가 나니 충분히 길게 하자)

     

     

    어쨌든 필터를 등록하고 컨텍스트의 빈으로 활용하기 위해 빈으로 등록했다. 또한 preFilter를 적용할 URL /login을 지정했고 토큰 생성을 위해 사용할 validTime과 secretKey를 받았다.

     

    실제 인증 및 토큰을 생성하는 과정이다. 토큰 생성을 위해 Jwts.builder()를 사용했고 subject로 username을 넣고 만료시간을 설정한 뒤, secretKey를 이용해 고유한 토큰을 생성한 걸 볼 수 있다. 마찬가지로 정상적인 로직이 이루어지면 헤더에 토큰과 사용자아이디를 추가하고 200상태코드를 넘겼다. 포스트맨으로 간단하게 테스트해보자

     

    미리 저장해 놓은 DB의 데이터를 입력하니 헤더가 잘 작성되었다! 상태가 404로 나온 건 서블릿에서 요청에 대한 처리를 만들지 않아서 그러니 넘어간다. 이제 발급받은 토큰으로 유효성을 검증하는 과정을 처리해보자.

     

     

    마찬가지로 정규표현식을 이용해 /api로 시작하는 모든요청은 인증 토큰을 발급받아햐 되게 설정했다. 헤더에서 발급받은 토큰과 username을 꺼내고(클라이언트가 다시 설정해야됨) 유효성을 검증하는 작업까지 완료했다. 검증 진행 중 예외가 터지지 않았다면 다음 필터로 넘어가 요청을 수행할 수 있다.

     

     

    마치며...

    기존 Cookie-Session방식에선 세션을 저장하기 위한 DB로 레디스를 사용했는데 JWT방식은 세션정보를 저장할 필요가 없다는 점이다.(구현 난이도는 엄대엄인 것 같다) 또한 JWT는 서버가 secret_key라는 아주 중요한 정보를 본인만 가지고 있어야 한다. 이는 RSA의 secret_key개념과 유사한 것 같다. 마이크로 서비스 환경에서 서버끼리 공유하는 secret_key를 잘 보관해야겠다.

    'java' 카테고리의 다른 글

    컬렉션 정리  (0) 2021.05.10
    Java Garbage Collector  (0) 2021.05.10
    BeanUtils copyProperties 사용법 및 주의사항  (0) 2021.05.04
    java 실행과정  (0) 2021.05.01
    HashMap이란?  (0) 2021.02.12

    댓글

Designed by Tistory.