
JWT는 JSON Web Tokens로 웹에서 사용하는 JSON기반 형식의 토큰.
JWT를 사용한 로그인/로그아웃에 대해 알기 위해서는 Token 기반 인증을 알아야한다!
1. 토큰 기반 인증이란?
Token
- 서버에서 클라이언트를 구분할 수 있는 유일한 값
- 서버에서 생성해서 클라이언트에게 전달한다.
- 클라이언트는 서버에 요청할 때마다 요청 내용과 함께 토큰을 전송한다. 서버에서는 토큰으로 유효한 사용자인지 확인한다.
Token 기반 인증
- 토큰 기반 인증
- 인증에 토큰을 사용하는 방식
- 특징
✔ 무상태성 (stateless)
☑ (server입장) token을 client에서 보관함으로 토큰 관리할 필요가 없음
✔ 확장성
☑ client가 여러 서버에 접근하는 경우 token을 쓰는 다른 로그인 시스템을 사용할 수 있고 무상태성으로 관리하기 편함
eg) 구글 계정 로그인 / 카카오 계정 로그인 등 sns 계정을 통한 로그인
✔ 무결성
☑ token 이 생성된 뒤에는 절대 수정되지 않음
2. JWT (Json Web Tokens)
- JWT : 토큰 기반 인증에서 주로 사용하는 토큰, json 형식으로 user(클라이언트)의 정보를 저장한다.
- 발급받은 JWT로 인증을 하려면 HTTP 요청 헤더 중에 Authorization 키 값에 Bearer + JWT토큰 값을 넣어 보내야 함.
- 헤더 / 내용 / 서명 구조
- 헤더 : 토큰의 타입, 해싱 알고리즘을 지정하는 정보
- Refresh Token : access 토큰은 유효기간이 지나면 사용이 어려움, 그 때 Refresh Token을 사용해 새로운 access token을 발급받는다.
- 서버에서 클라이언트에 access/refresh token을 만들어 주고 DB에 refresh token을 저장해둔다.
- 클라이언트에서 만료된 access token으로 인증을 요청하면 서버에서 토큰 만료 에러를 전달한다.
- 클라리언트는 저장해둔 refresh token과 함께 새로운 access token발급을 요청한다.
- 서버는 DB에 저장한 refresh token을 조회해 클라이언트가 전달한 것고 같은지 확인 후 유효한 refresh token이라면 새로운 access token을 생성한 뒤 응답한다.
- 클라이언트는 저장된 access token과 함께 인증을 필요로하는 api를 호출
3. JWT[Json Web Token] 서비스 구현
- 실제로 JWT를 생성하고 검증하는 서비스
- 의존성 추가
- 토큰 제공자 추가
- Application.yml (프로퍼티- 설정값)
JWT 토큰을 만드려면 이슈 발급자(issuer), 비밀키(secret_key) 필수 설정
- config/jwt/JwtProperties.java
해당 값들을 변수로 접근하는데 필요한 코드 작성
@ConfigurationProperties 사용
- java 클래스에 프로퍼티값을 가져와서 사용하는 애너테이션
- config/jwt/TokenProvider.java
- 토큰 생성(makeToken) / 유효성 검증(validToken) / 토큰 기반 인증 정보, 유저 ID를 가져오기(getAuthentication/getUserId)
- JWT 토큰 서비스 테스트를 위한 mocking용 객체 생성
- 리프레시 토큰 도메인 구현
- DB에 저장하는 정보이므로 Entity, Repository를 추가해야 함.
- domain/RefreshToken.java
- repository/RefreshRepository.java
-
토큰 필터 구현

- 필터는 실제로 각종 요청을 처리하기 위한 로직임
- 전달되기 전후에 URL 패턴에 맞는 모든 요청을 처리하는 기능을 제공함.
- 요청이 오면 헤더값을 비교해서 토큰이 있는지 확인함
- 유효한 토큰이면 시큐리티 컨텍스트 홀더에 인증 정보를 저장함.
Security Context Holder : Security Context 객체를 저장하는 객체
- Security Context는 인증객체가 저장되는 보관소로 인증 정보가 필요하면 언제든지 인증 객체를 꺼내 사용할 수있다.
- 이 클래스는 thread마다 공간을 할당하는 thread local에 저장되므로 코드의 아무곳에서나 참조 가능/다른 theread와 공유하지 않아 독립적 사용이 가능
4. Token API 서비스 구현
- Refresh Token을 전달 받아 Token Provider를 사용해 새로운 Access Token을 만드는 Token Service Class구현
1. 토큰 서비스 추가하기
- service/UserService.java
- findById(Long userId) : 전달받은 user id로 user를 검색해서 전달
- service/RefreshTokenService.java
- findByRefreshToken() : 전달받은 refresh token으로 refresh token 객체를 검색해서 전달
- service/TokenService.java
- createNewAccessToken() : 전달받은 Refresh Token으로 token 유효성 검사 진행, 유효한 token이면 refresh token으로 사용자 id 찾음, tokenProvider의 generateToken()을 호출해새로운 access token을 생성
2. 컨트롤러 추가하기
- 실제로 토큰을 발급받는 API
- dto/CreateAccessTokenRequest
- dto/CreateAccessTokenResponse
- 토큰 생성 요청과 응답을 담당하는 DTO class
- service/TokenApiController.java
- 실제로 client에게 요청 받고 처리할 컨트롤러