요약하자면, 이전에 만든 API 에 JWT 를 이용한 인증을 도입해보았다.
쉽게 말해서 인증은 '누구인지' 확인하는 행위이고 인가는 '할 수 있는지' 확인하는 행위이다. 인증은 인가로 이어질 수 있지만, 인가는 인증으로 이어지지는 않을 수 있다.
JWT 란 JSON Web Token 으로 보안이 적용된 JSON Object 를 주고받을 수 있는 표준이다.
JWT 는 들어보기만 하고 써보는 건 처음이라 궁금해서 이것저것 찾아보았다.
JWT 는 쿠키 혹은 로컬스토리지에 보통 저장하는데, 둘 다 보안에 취약하지만 그래도 HttpOnly 를 적용한 쿠키가 그나마 나은 옵션이라고 여겨지고 있다. 기본적으로 브라우저에 있는 정보들은 자바스크립트로 접근이 가능하기 때문에 XSS 공격에 취약하다고 여겨지고 있다.
JWT 의 경우 한번 탈취되면, 상당히 골치아파진다. 그렇다고 해서 매번 만료 주기를 짧게 잡으면, 사용자가 사이트를 켜놓고 딴짓을 하게 된다고 쳤을 때, 이용하는 중간 중간에 계속 로그인을 새로 해주어야 한다.
이 경우 토큰을 2개 발급하여, 1개는 Refresh Token
용도로 사용하고 1개는 일반 Access Token
을 만든다. Access Token
은 짧은 만료 주기를 갖고 계속 만료가 되는 형태가 될 것이고, Refresh Token
은 긴 만료주기를 갖고 계속 Access Token
을 업데이트 하는 전략을 사용할 수 있다.
물론 두 토큰 모두 탈취당하면 답이 없다.
비교군으로는 세션 기반 인증이 있다.
stateless vs stateful
세션 기반 인증과 JWT 의 가장 커다란 차이는 아무래도 'stateless 로 구현 가능하냐' 인 것 같다. 그러나 JWT 인증도 여러가지 보안 요소를 고려하다보면 결국 실제 서비스에서는 'stateless' 는 될 수도 있고 안 될 수도 있다.
도메인에 대한 제약이 상대적으로 적음
MSA (Micro Service Architecture) 가 유행하며, JWT 가 기본적으로 도메인 제약이 상대적으로 적은 인증 방식이라는 것 때문에 유행하는 것도 있는 것 같다.
@Bean
, @Value
, @Configuration
애노테이션 내용을 정리했다2개는 이전에 정리해보았던 애노테이션이라 @Value
만 한번 정리해보았다. 스프링의 BeanPostProcessor
를 통해 실행되는지 처음 알았고 SpEL 문법 활용이 가능한 것도 처음 알게 되었다.
@Setter
사용을 자제하자Jackson
라이브러리는 @Setter
없이도 객체 매핑을 잘 해주어서, 사실상 @Setter
가 필요 없었다. 필요할 때만 쓰자.
클라이언트에게 메세지를 줄 때는 완곡한 표현을 사용하자. 최근 회사 업무에서도 많이 느끼고 있는데, 서비스 이용 중 예외가 발생하면 고객은 내가 작성한 딱딱한 예외 메세지를 받고 어떤 일이 일어났는지 파악하게 된다. 인터넷 끊김과 같은 케이스도 생각하며 예외 메세지를 조금만 더 완곡하게 표현해 더욱 포용력 있는 답을 해보자.
의미를 가진 코드 조각은 메서드로 추출해서 가독성을 챙기자.
validUser
대신 registeredUser
코드의 의미는 간결하면서 명확하게 드러날수록 좋다. valid
는 registered
보다는 덜 구체적이므로 생각을 한번만 더 해보고 조금 더 구체적인 표현이 없는지 생각해보자.
@DisplayName
작성 시 클래스명의 디커플링을 조심하자여기서 UserLoginException
이라는 예외 이름을 변경하여, 디커플링 되는 경우가 생겨버렸다. 다음부터 이런 경우를 조금만 더 생각해보자.