[ STUDY ]/Spring Boot

[ JWT를 활용한 Spring Security ] JWT 토큰 생성

김강니 2024. 9. 20. 22:17

JWT?

Json Web Token의 줄임말로 JSON 객체를 사용해 정보를 안전하게 전송하는 토큰 기반 인증 방식

 

  • Stateless 방식으로 서버가 클라이언트의 상태를 저장하지 않고, 클라이언트가 요청을 보낼때 제공한 JWT를 기반으로 인증을 처리
    무상태(stateless): 클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존하지 않음을 의미
    장점 
    - 특정 DB/서버에 의존하지 않아도 인증 가능
    - 서버의 확장성이 높기 때문에 대량의 트래픽 발생 시에도 대처가 수월
    단점 

    - 클라이언트의 요청에 상대적으로 Stateful 보다 더 많은 데이터가 소모

    - 데이터 노출로 인한 보안적인 문제
  • 사용자 인증, 정보 교환에 사용

유효 기간과 서명을 포함하여 변조되지 않았음을 보장

 

⬇️⬇️ Stateless의 반대는?? ⬇️⬇️

더보기

Stateless의 반대는?? Stateful
Stateful은 stateless와 반대로 서버가 클라이언트의 상태를 저장하고 있다.
그니까 클라이언트가 요청을 보내면 이전의 요청도 기억하고 있어서 요청들의 관계가 이어져있는..?그런 느낌

stateless는 요청마다 각각 처리가 되기때문에 이전 요청을 기억 ❌❌

단점은 서버가 문제가 발생해서 다른 서버를 사용해야할때 다른 서버에서는 이전의 요청들을 기억하고 있지않기 때문에 문제가 발생..!!

나중에 더 구체적으로 알아보고 포스팅해야겠다..!!

 

 

JWT 토큰 발급 과정

1. 사용자 인증

Optional<User> user = userRepository.findByEmail(email);
if(user.isEmpty()) {
    throw new IllegalArgumentException("User not found");
}

 

사용자가 로그인을 시도하면 이메일을 기반으로 DB에서 사용자 조회 -> 사용자가 존재하지 않으면 예외 발생

 

 

2. JWT 토큰 생성

String token = Jwts.builder()
        .setSubject(email)
        .claim("role", role)
        .claim("userId", userId)
        .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
        .signWith(key)
        .compact();

 

사용자 인증이 완료되면(1번) 사용자의 email, role, ID 정보를 포함한 JWT 토큰을 생성한다.

setSubject(email)
이메일 설정
claim()
사용자의 역할과 ID정보 설정
setExpiration()
토큰 만료 시간 설정

static final long EXPIRE_TIME = 1000 * 60 * 60 * 24; // 1일
토큰의 만료 시간은 1일로 설정, 1일 이후 토큰 만료
* 추후에 refresh와 access 구현예정
signWith()
비밀키를 사용해 서명

static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 비밀키
HS256 알고리즘을 사용하여 JWT 토큰 서명에 사용할 비밀키를 생성

 

 

3. 토큰 전달

return token;

 

생성된 토큰은 클라이언트에게 반환 -> 이후에 클라이언트는 API요청시에 헤더에 토큰을 포함시켜 요청을 보낸다.

 

 

4. API요청시에 토큰 검증

public Boolean validateToken(String token, String username) {
    final String extractedUsername = extractUsername(token);
    return (extractedUsername.equals(username) && !isTokenExpired(token));
}

 

이전 글에서 작성한 JwtRequestFilter에서 validateToken()메소드를 사용하여 유효성을 검증한다.

 

 

다음 포스팅부터  refreshToken이랑 AccessToken 공부하고 구현해보겠음..!!