역할/권한

Seoyeon·2025년 9월 1일
0

백엔드기초

목록 보기
14/17

Spring Security에서 역할(Role)과 권한(Authority)

1. 역할(Role)

  • 사용자의 기능/책임을 그룹화한 상위 개념

  • 여러 권한(Authorities)을 묶어서 표현하는 경우가 많음

  • 관례적으로 ROLE_ 접두사를 붙여 사용

  • 예시:

    • ROLE_ADMIN → 관리자 그룹
    • ROLE_USER → 일반 사용자 그룹

2. 권한(Authority)

  • 특정 리소스/작업에 대한 세부적 허가

  • 역할보다 더 구체적인 단위

  • ROLE_ 접두사가 없는 문자열로 구분

  • 예시:

    • "READ_PRIVILEGE" → 읽기 권한
    • "WRITE_PRIVILEGE" → 쓰기 권한
    • "DELETE_PRIVILEGE" → 삭제 권한

3. 스프링 시큐리티에서 역할과 권한 매핑

(1) UserDetails / GrantedAuthority

  • 스프링 시큐리티는 내부적으로 모든 권한을 GrantedAuthority 로 처리
  • ROLE_ADMIN 같은 것도 결국은 GrantedAuthority("ROLE_ADMIN")
  • SimpleGrantedAuthority 로 감싸서 넣어줌
new SimpleGrantedAuthority("ROLE_ADMIN"),  // 역할
new SimpleGrantedAuthority("WRITE")        // 권한

(2) UserPrincipal 예시

public class UserPrincipal extends User {
    private final Long userId;

    public UserPrincipal(com.jeulog.domain.User user) {
        super(user.getEmail(), user.getPassword(), List.of(
                new SimpleGrantedAuthority("ROLE_ADMIN"), // 역할
                new SimpleGrantedAuthority("WRITE")       // 권한
        ));
        this.userId = user.getId();
    }

    public Long getUserId() {
        return userId;
    }
}
  • ROLE_ 붙이면 Role로 인식
  • 붙이지 않으면 Authority로 인식

(3) SecurityFilterChain에서 적용

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/auth/login", "/auth/signup").permitAll()
            .requestMatchers("/user").hasAnyRole("USER", "ADMIN") // 역할 검사
            .requestMatchers("/admin").access(
                new WebExpressionAuthorizationManager(
                    "hasRole('ADMIN') and hasAuthority('WRITE')" // 역할 + 권한 조합
                )
            )
            .anyRequest().authenticated()
        )
        .csrf(AbstractHttpConfigurer::disable)
        .formLogin(login -> login
            .loginPage("/auth/login")
            .loginProcessingUrl("/auth/login")
            .usernameParameter("username")
            .passwordParameter("password")
            .defaultSuccessUrl("/")
        )
        .rememberMe(rm -> rm
            .rememberMeParameter("remember")
            .tokenValiditySeconds(2592000)
        )
        .build();
}

4. 권한/역할 검사 메서드

  • 역할(Role)

    • .hasRole("ADMIN") → 내부적으로 ROLE_ADMIN과 매칭
    • .hasAnyRole("ADMIN", "USER")
  • 권한(Authority)

    • .hasAuthority("WRITE")
    • .hasAnyAuthority("READ", "WRITE")
  • 역할 + 권한 조합

    • .access("hasRole('ADMIN') and hasAuthority('WRITE')")

5. 주의할 점

  1. hasRole("ADMIN") 은 내부적으로 "ROLE_" prefix를 붙임 → 실제 GrantedAuthority에는 "ROLE_ADMIN" 있어야 함.
  2. 권한 체크(hasAuthority)는 접두사 안 붙임.
  3. DB에서 Role/Authority를 어떻게 설계하느냐에 따라 매핑 로직(UserDetailsService에서 SimpleGrantedAuthority 변환)이 달라짐.
  4. Role과 Authority를 혼용하는 경우, 규칙(접두사 여부)을 헷갈리지 않도록 통일하는 게 중요.

0개의 댓글