[Spring/SpringBoot] JWT의 핵심은 암호화가 아닌 인가/인증이다 (feat.JWT 복호화 사이트)

pintegral·2022년 10월 8일
1

Spring/Spring Boot

목록 보기
4/8
post-thumbnail

1. 토큰화(secreKey로 특정 알고리즘 방식 이용하여 token 인코딩)


// JwtTests.java

@Test
    @DisplayName("accessToken 을 얻는다.")
    void t5() {

        // 회원번호가 1이고
        // username이 admin 이고
        // ADMIN 역할과 MEMBER 역할을 동시에 가지고 있는 회원정보 구성
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", 1L);
        claims.put("username", "admin");
        claims.put("authorities", Arrays.asList(
                new SimpleGrantedAuthority("ADMIN"),
                new SimpleGrantedAuthority("MEMBER"))
        );

        // 지금으로부터 5시간 유효기간 가지는 토큰 생성
        String accessToken = jwtProvider.generateAccessToken(claims, 60 * 60 * 5);

        System.out.println("accessToken : " + accessToken);

        assertThat(accessToken).isNotNull();
    }

accessToken을 copy 해서 https://jwt.io/ 로 들고 가면

이런 식으로 header, payload(data body), signature 복호화 가능하다.

secretKey를 이용하여 암호화를 했다기보다는 base64 알고리즘으로 인코딩했다고 보는 게 더 맞는 표현일 것이다.

따라서 별도의 비밀번호 없이도 accessToken 디코딩 가능하다.

정리하자면 JWT(access Token)는 복호화가 아닌 쉽게 디코딩되므로 token 비밀번호 같은 중요한 개인정보는 포함하지 않는 것이 좋다.

나중에 클라이언트로부터 서버에 access Token을 받았을 때 이 access Token은 secretKey로 base64 알고리즘 인코딩을 한 게 맞는지, 다른 누군가에 의해 변조되지 않았는지(verify-토큰 유효화 여부 true/false로 확인) 인가/인증하는 것이 JWT의 주 목적이라고 볼 수 있겠다.

2. 토큰화 해제 (+ token 이용하여 claims(데이터 정보들) 얻기)


payload 부분에는 토큰에 담을 정보가 들어있다. 여기에 담는 정보의 한 '조각' 을 클레임(claim)이라고 부른다.

//JwtProdiver.java

/* accessToken 유효화 인증 */
    public boolean verify(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /* accessToken의 claims -> map으로 */
    public Map<String, Object> getClaims(String token) {
        String body = Jwts.parserBuilder()
                .setSigningKey(getSecretKey())
                .build()
                .parseClaimsJws(token)
                .getBody()
                .get("body", String.class);

        return Utility.json.toMap(body);
    }
// JwtTests.java

@Test
    @DisplayName("accessToken 을 통해서 claims 를 얻을 수 있다.")
    void t6() {
        // 회원번호가 1이고
        // username이 admin 이고
        // ADMIN 역할과 MEMBER 역할을 동시에 가지고 있는 회원정보를 구성
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", 1L);
        claims.put("username", "admin");
        claims.put("authorities", Arrays.asList(
                new SimpleGrantedAuthority("ADMIN"),
                new SimpleGrantedAuthority("MEMBER"))
        );
        // 구성 끝

        // 지금으로부터 5시간의 유효기간을 가지는 토큰을 생성
        String accessToken = jwtProvider.generateAccessToken(claims, 60 * 60 * 5);

        System.out.println("accessToken : " + accessToken);

        assertThat(jwtProvider.verify(accessToken)).isTrue();

        Map<String, Object> claimsFromToken = jwtProvider.getClaims(accessToken);
        System.out.println("claimsFromToken : " + claimsFromToken);
    }

claimsFromToken:{id=1, authorities=[{authority=ADMIN}, {authority=MEMBER}], username=admin}
이렇게 토큰으로부터 얻은 claim 정보 확인 가능하다

profile
문제를 끝까지 해결하려는 집념의 개발자

0개의 댓글