JWT

모바일 앱 백엔드를 개발하면서 눈이 많이 뜨였다. 설계자의 시점에서 프로젝트를 바라볼 필요가 있기에 많은 노력과 고생이 들어갔다. 아직 대학교 4학년이지만 어느정도 프로젝트를 거시적으로 바라보며 이 작업이 왜 필요하고 어떻게 설계하면 좋을지에 대한 감각이 생긴것 같아서 행복한 요즘이다. 이번 시간엔 카카오 OAuth 2.0 + Spring Security + JWT + Redis를 조합하여 인증 시스템을 설계한 과정을 포스팅해볼 것이다. 각각의 기술을 선택한 이유와 세부적으로 필터체인을 설계한 과정을 공유할 생각이다. 왜 JWT일까? 전통적인 웹 애플리케이션에선 세션 방식이 일반적이다. 로그인할 땐 브라우저가 자동으로 쿠키 전송 → 서버가 세션 저장소에서 조회 → 사용자 정보 확인 이후의 ..
JWT 기반 인증을 쓰다 보면 “DB에서는 이미 사용자가 삭제됐는데, 앱에서는 여전히 로그인 상태로 남아있는” 이상한 상황을 경험할 때가 있다. 나 역시 최근 이런 문제를 직접 겪었다. 로그아웃도 안 한 상태에서 DB에서 바로 사용자 데이터를 삭제했더니 앱을 껐다 켜도 여전히 로그인 상태로 유지됐다. 로그아웃을 해도 잘 안되고 결국 앱 캐시를 지우니까 그제야 초기화되었다. 처음엔 단순한 캐시 문제인 줄 알았는데 파악해보니까 원인은 훨씬 근본적이었다. 바로 JWT의 무상태 구조와 블랙리스트의 동작 방식 때문이다. JWT의 본질: 서버는 아무것도 기억하지 않는다. JWT는 서버가 세션을 저장하지 않는다. 토큰 안에 사용자 정보, 만료 시간, 서명이 모두 들어있기 때문이다. 서버는 요청마다 서명이 유효한가..
JWT는 로그인한 사용자를 인증하기 위해 가장 널리 쓰이는 방식이다. 서버가 세션을 직접 저장하지 않아도 되기 때문에 무상태이면서도 서명 검증만으로 사용자를 확인할 수 있다. 근데 단순한 만큼 치명적인 약점이 있다. 서버가 한 번 발급한 토큰을 강제로 무효화할 수 없다는 점이다. 서버가 잃어버린 통제권 JWT는 한 번 발급되면 그 안에 exp(만료시간)이 고정된다. 이 말은 서버가 그 토큰을 회수하거나 취소할 방법이 없다는 뜻이다. 사용자가 로그아웃 해도 기존 토큰은 유효하고 비밀번호 변경해도 이전 토큰으로 접근 가능하고 토큰이 유출되면 서버는 막을 방법이 없다. 결국에 서버가 다시 상태를 관리하는 방법을 찾아봐야 한다. 그게 바로 블랙리스트 구조이다. 블랙리스트란? JWT는 기본적으로 sta..
러닝 앱 백엔드를 개발하면서 JWT 토큰 발급, 카카오 OAuth, 복잡한 보안 설정을 매번 거쳐서 API를 테스트하기엔 너무 번거로웠다. 특히 @AuthUser AuthenticatedUser user 파라미터를 사용하는 Controller들을 테스트할 때마다 실제 JWT 토큰을 만들어야 하는 상황이었다. 따라서 메인 로직은 건드리지 않으면서 테스트만을 위한 postman 프로필을 만들어 Mock 인증으로 우회하는 방법을 사용했다. 겪으면서 알게 된 것들이 꽤 있으므로 공유해보겠다. 구조📁 config ├── SecurityConfig.java (메인 보안 설정 - JWT 기반) ├── SecurityConfigPostman.java (테스트용 보안 설정 - Mock 기반) ├── Web..
이번 시간엔 마지막 시간이다. 먼저 CORS에 대해 알아보자. CORS 설정 CORS란 프론트엔드 서버와 백엔드 서버를 따로 띄워서 브라우저 단에서 테스트하면 CORS 문제 때문에 데이터가 날아오지 않거나 데이터를 부어줄 수 없는 문제가 생긴다. 리액트랑 스프링을 같이 짜면 주로 겪게 되는 문제이다. 우리의 클라이언트가 웹 브라우저를 통해서 사이트에 접속하게 되면 프론트 서버에서 react나 vue를 응답해준다. 보통 프론트엔드 서버는 포트번호 3000번을 띄워서 테스트를 하게 되고 응답받은 페이지에서 특정한 내부 데이터를 API 서버한테 호출하게 되면 API 데이터는 8080포트에서 응답이 된다. 이렇게 되면 두 개의 서버 포트 번호가 다르므로 웹 브라우저 단에서 교체 출처 리소스 공유를 금지시키..
앞 시간까지 로그인 구현, 로그인이 성공했을 때 jwt를 반환하는 것까지 성공했다. 서버를 띄워놓고 바디에 id와 비밀번호 띄워놓고 토큰이 응답헤더에 답겨오고 이 토큰을 복사해서 특정 다른 경로에 요청을 진행할 때 요청 헤더에 authorization 키에 토큰을 넣어서 요청을 전송하면 된다. 전송하면 main Controller 같은 메인 페이지는 권한 없이 접근 할 수 있기에 응답되지만 admin 경로 같은 경우엔 접근 거부가 된다. 토큰을 검증해주는 필터를 아직 등록해주지 않아서 토큰을 통해서 인증을 진행할 수 없기 때문이다. 이번 시간엔 토큰을 검증해서 내부엔 stateless지만 한 번의 요청에 대해 잠깐의 세션을 만드는 토큰 검증 필터를 만들 것이다. 앞서 이야기 한대로, 로그인 성공 시 JW..
이번에는 본격적으로 JWT(Json Web Token)를 활용한 인증 기능을 구현해보도록 하겠다. JWT는 크게 두 가지 역할을 수행해야 한다. 첫 번째는 토큰 발급이고, 두 번째는 토큰 검증이다.사용자가 로그인에 성공하면 서버는 사용자 정보를 바탕으로 JWT를 발급하게 되고, 사용자는 이후부터 이 JWT를 Authorization 헤더에 실어 모든 요청에 함께 보낸다. 서버는 해당 요청을 처리하기 전에 이 JWT가 유효한지를 먼저 확인해야 한다. 즉, 이 토큰이 우리 서버가 발급한 것이 맞는지, 유효 기간이 만료되지는 않았는지를 검증하는 로직이 반드시 필요하다. 이런 JWT의 발급과 검증을 전담할 JWTUtil이라는 클래스를 만들 것이다. 이 클래스는 토큰을 생성하거나 토큰에서 사용자 정보를 추출하고 ..
이번 시간엔 로그인 필터 구현과 db 기반 검증 로직을 수행해볼 것이다. 점점 어려워지고 있는데 확실한건 로직을 파악하는 실력은 많이 늘고 있는 것 같다. 먼저 이 로그인 모식도를 보자. login로직을 두 가지로 나눌 것이다. 처음엔 로그인 요청을 받아서 이것을 처리하는 것을 진행하고 이후에 받은 username과 password 값을 가지고 DB를 기반으로 검증을 진행해보자. JWT를 할 때는 여기선 폼 로그인 방식을 disable 했기 때문에 우리가 만들어서 구현시킬 것이다. 동작 방식 사용자의 요청이 필터를 타고 id와 비밀번호를 가지고 들어오면 UsernamePasswordAuthenticationFilter가 그 username과 password를 꺼내서 로그인을 진행한다고 Authenti..
hskhsmm
'JWT' 태그의 글 목록