[그림일기 서비스 보고 공부하기] getAuthentication에서 UserDetailsService를 사용하기 vs 사용하지 않기

오젼·2024년 10월 3일
0

JwtTokenProvider 리팩토링 중에 고민되는 부분이 생겼다.

그림일기 서비스에선 getAuthentication 메서드에서 UserDetailsService를 사용하지 않았고
나는 UserDetailsService를 사용했었다.

무슨 차이가 있나 봤더니 토큰 검증 과정에서 db를 조회 하느냐, 조회 하지 않느냐의 차이였다.

그림일기 서비스에서는 db 조회 없이, 토큰에 있는 username, role을 파싱해서 해당 내용으로 인증 정보를 만든다.

나는 토큰에 있는 username을 바탕으로 db에서 회원을 조회해서 조회한 내용으로 인증 정보를 만든다.

AI들이 주는 예시에서도 UserDetailsService를 사용했고 다른 코드들에서도 UserDetailsService를 사용하는 경우가 많았다.

db 조회 없이 사용하면 시간이 단축된다는 장점이 있지만 보안상 문제가 있을 수도 있다.

그런데 다시 애플리케이션 흐름을 짚어보니 수강신청이나 회원탈퇴 같은 로직에서 어차피 username을 이용해서 db 조회를 거친 다음 과정이 진행이 되고 있었다.

또 JWT에 포함할 내용이 username과 role로 민감한 정보도 아니었기에 보안상 문제로 db 조회를 매번 거치는 것보다 JWT에 포함된 정보를 바로 가져오는 것이 더 맞아 보였다.

그래서 그림일기 서비스와 마찬가지로 토큰에 username, role 정보를 포함하고 Spring Security에 인증 정보를 저장할 때 db 조회 없이 해당 정보를 바로 JWT에서 파싱해서 사용하는 것으로 결정했다.

이전)

public Authentication getAuthentication(String token) {
        String username = getUsernameFromJWT(token);
        UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
        return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    }

이후)

public Authentication getAuthentication(String token) {
    Claims claims = Jwts.parserBuilder()
            .setSigningKey(key)
            .build()
            .parseClaimsJws(token)
            .getBody();
    
    String username = claims.getSubject();
    String role = claims.get("role", String.class);
    
    List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role));
    
    return new UsernamePasswordAuthenticationToken(username, null, authorities);
}

-> 여기서 더 바꿈
-> https://velog.io/@zhy2on/그림일기-서비스-보고-공부하기-JWT에-username-대신-Long-userId를-넣기-JwtAuthenticationToken-사용하기

0개의 댓글