Spring Security ROLE_ 접두사

양성준·2025년 7월 2일

스프링

목록 보기
44/49

Spring Security는 “역할(Roles)”과 “일반 권한(Authorities)”을 구분하기 위해 ROLE 접두사를 붙임
Spring Security는 내부적으로 모든 권한을 GrantedAuthority로 다루는데,
그중에서도 @Secured, hasRole(), hasAnyRole() 등 “역할 기반 접근 제어”를 할 떄는,
→ ROLE
접두사가 붙은 권한만을 역할(Role)로 간주

hasRole과 ROLE_ 접두사

  • Spring Security에서 hasRole('ADMIN')을 사용하면 내부적으로 "ROLE_ADMIN" 권한이 있는지 검사.
  • 즉, "ADMIN"이 아니라 "ROLE_ADMIN"이라는 권한 문자열이 Security Context에 저장되어 있어야 한다.
@PreAuthorize("hasRole('ADMIN')") // 내부적으로 "ROLE_ADMIN" 검사

hasAuthority와 접두사

  • 반면, hasAuthority('ADMIN')를 사용하면 접두사 없이 "ADMIN"이라는 권한 문자열을 그대로 검사.
  • "ROLE_"이 붙은 권한을 검사하려면 hasAuthority('ROLE_ADMIN')로 명시해야 합니다.
@PreAuthorize("hasAuthority('ADMIN')")      // "ADMIN"만 검사
@PreAuthorize("hasAuthority('ROLE_ADMIN')") // "ROLE_ADMIN"만 검사

Enum에 ROLE_을 붙이지 않는 권장 패턴

  • 권한을 Enum으로 관리할 때는 Enum 값에는 ROLE_ 접두사를 붙이지 않는 것이 가장 깔끔하다.
public enum Role {
  USER, CHANNEL_MANAGER, ADMIN
}
  • 이 경우, 권한을 반환(getAuthorities)할 때만 "ROLE_" 접두사를 붙여주는 방식이 가장 권장됨.
// UserDetails
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
  return List.of(new SimpleGrantedAuthority("ROLE_" + userDto.role().name()));
}

// 추후 SecurityContext에는 ROLE_ 로 저장됨.
UsernamePasswordAuthenticationToken authentication =
    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
  • 이렇게 하면,
    • Enum 값은 "ADMIN" 등으로 간결하게 유지
    • Security Context에는 "ROLE_ADMIN" 등 Spring Security 표준에 맞는 권한이 저장
    • hasRole('ADMIN')으로 권한 체크가 자연스럽게 동작
public enum Role {
    USER("ROLE_USER"),
    ADMIN("ROLE_ADMIN"),
    MANAGER("ROLE_MANAGER");

    private final String authority;

    Role(String authority) {
        this.authority = authority;
    }

    public String getAuthority() {
        return authority;
    }
}

// CustomUserDetailsService
       @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            // 사용자의 역할을 Spring Security 권한으로 변환
            return Collections.singletonList(
                new SimpleGrantedAuthority(user.getRole().getAuthority()));
        }
  • 또는, 이렇게 enum의 필드에 ROLE_ 접두사를 붙인 role을 넣어놓고, 쓸때만 getRole().getAuthority()로 꺼내주면 된다.

실무에서의 권장 방식

  • Enum에는 ROLE_을 붙이지 않는다.
  • getAuthorities()에서 "ROLE_" 접두사를 붙여 반환한다.
  • 권한 체크는 hasRole('ADMIN')을 사용한다.
  • 만약 hasAuthority를 써야 한다면, 저장된 권한 문자열에 따라 정확히 맞춰 사용한다.
profile
백엔드 개발자를 꿈꿉니다.

0개의 댓글