본문 바로가기

IT

JWT와 Security를 활용한 인증, 인가 구현 1 ( JWT 토큰 생성)

728x90

JWT에 대한 이론은 https://sh970901.tistory.com/85 포스팅했으니 참고하도록 하자.

 

1. build.gradle에 JWT와 Security 관련 라이브러리를 추가해준다.

 
 //JWT 관련 
 implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
 runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
 runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
 
 //Security 관련
 implementation 'org.springframework.boot:spring-boot-starter-security'
 implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
 testImplementation 'org.springframework.security:spring-security-test'
 
 //Spring Data Jpa
 implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

2. application.yml에 사용할 시크릿 키를 설정해준다. 

이 키를 활용하여 JWT 토큰을 만들고 나중에 요청이 들어오면 토큰을 해석할 수 있다.

custom:
  jwt:
    secretKey: secretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKey

3. JwtConfig 파일을 만들어 secretKey를 Base64 인코딩해서 받아오자.

@Configuration
public class JwtConfig {
    @Value("${custom.jwt.secretKey}")
    private String secretKeyPlain;

    @Bean
    public SecretKey jwtSecretKey() {
        String keyBase64Encoded = Base64.getEncoder().encodeToString(secretKeyPlain.getBytes());
        return Keys.hmacShaKeyFor(keyBase64Encoded.getBytes());
    }
}

4. Jwt 관련 로직처리하는 컴포넌트를 추가하자. 

토큰이 유효한지 확인하는 함수, 토큰 생성 함수, 토큰으로 정보를 얻는 함수를 추가했다.

@Component
@RequiredArgsConstructor
public class JwtProvider {

    private final SecretKey jwtSecretKey;

    private SecretKey getSecretKey() {
        return jwtSecretKey;
    }
    
    //토큰이 시크릿키로 분해되는 함수인지 확인
    public boolean verify(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    //토큰으로부터 정보얻기
    public Map<String, Object> getClaims(String token) {
        String body = Jwts.parserBuilder()
                .setSigningKey(getSecretKey())
                .build()
                .parseClaimsJws(token)
                .getBody()
                .get("body", String.class);

        return Util.json.toMap(body);
    }

    //정보와 시크릿 키, 시간을 넣어 압축해 토큰 생성
    public String generateAccessToken(Map<String, Object> claims, long seconds) {
        long now = new Date().getTime();
        Date accessTokenExpiresIn = new Date(now + 1000L * seconds);

        return Jwts.builder()
                .claim("body", Util.json.toStr(claims))
                .setExpiration(accessTokenExpiresIn)
                .signWith(getSecretKey(), SignatureAlgorithm.HS512)
                .compact();
    }
}