Spring Security - JWT 사용 시 커스텀 UserDetails DTO 정의

TopOfTheHead·2025년 12월 20일

Spring Security

목록 보기
7/26

커스텀UserDetails 구현체를 생성
。기존 UserDetails개별 사용자의 이름, PW, 권한 등의 세부정보를 추가로 정의하여 현재 로그인유저의 정보를 추가로 포함하는 UserDetails 구현체를 정의
UserDetailsService / UserDetails

。해당 UserDetails 구현체원본 유저 테이블에 저장된 데이터를 추출하여 Spring Security에 의해 인증이 수행되는 DTO 역할을 수행한다.

Controller@AuthenticationPrincipal을 통해 해당 UserDetail 구현체에 현재 로그인중인 Authentication 객체principal을 주입하여 @PathVariable 등을 사용하지 않아도 현재 로그인한 사용자의 principal 정보를 가져올 수 있음

  • UserDetails 구현체템플릿 역할의 인터페이스 정의
    。해당 UserDetails 구현체가 수행할 동작을 정의
    인증이 끝난 후 어플리케이션에서 활용할 사용자 정보를 포함해야하므로, Password는 제외
public interface CurrentUser {
	UUID getId();
  	String getEmail();
	UserRole getRole();
}
  • UserDetails 구현체 클래스 정의
    。해당 UserDetail 구현체Controller에서 @AuthenticationPrincipal에 의해 주입되서 활용됨

    UserDetails 인터페이스 구현 시 getUsername(), getPassword()만 구현
@Getter
@Accessors(chain = true)
public class CurrentUser implements UserDetails {
    @Setter
    private Long id;
    private String email;
    private String name;
    private String nickName;
    @Setter
    private Role role;
    private Map<String, Object> attributes;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(
                new SimpleGrantedAuthority("ROLE_" + this.role.name())
        );
    }
    @Builder
    private CurrentUser(
            String email,
            String nickName
    ){
        this.email = email;
        this.nickName = nickName;
        this.name = nickName;
    }
    public static CurrentUser from(Users user){
        if(user == null) throw new CustomException(ErrorCode.USER_NOT_FOUND, "계정이 없어 UserDetails의 생성이 불가능합니다.");
        return CurrentUser.builder()
                .nickName(user.getNickname())
                .email(user.getEmail())
                .build()
                .setId(user.getUserId())
                .setRole(user.getRole());
    }
}

new SimpleGrantedAuthority("ROLE_" + role.name())를 통해 로그인사용자역할을 정의하여 권한 설정하도록 설정하기.
▶ 이후 서비스 레이어 방어로직 또는 auth.requestMatchers(SecurityPath.ADMIN).hasRole("ADMIN"); 등을 통한 권한 검증 시 활용

이후 JWT 필터를 통해 JWT 토큰으로 인증 후 @AuthenticationPrincipal를 통해 인증Authentication 구현체DefaultCurrentUser가 아닌, CurrentUser로 주입
。해당 JWT 토큰인증이 끝난 경우 CurrentUser 정보를 저장하여 SecurityContextHolder 내 보관됨

@RestController
@RequestMapping("/api/profiles")
public class ProfileController {
    @GetMapping("/me")
    public ResponseEntity<?> getMyProfile(@AuthenticationPrincipal CurrentUser currentUser) {
  //
        UUID userId = currentUser.getId();
        String email = currentUser.getEmail();
        //
        return ResponseEntity.ok("유저 ID: " + userId + ", 이메일: " + email);
    }
}
profile
공부기록 블로그

0개의 댓글