Files
spring-boot-examples/docs/security/05_메서드 수준 보안.md
2025-04-08 19:56:24 +09:00

7.4 KiB

아래는 "스프링 시큐리티" 책의 5장에 포함될 "메서드 수준 보안 설정"과 "@PreAuthorize, @Secured 어노테이션 활용"에 대한 내용입니다. 이 설명은 개념을 명확히 하고 실무에서 사용할 수 있는 예제를 포함해 작성되었습니다.


5장. 인가와 권한 관리

5.3 메서드 수준 보안 설정

URL 기반 접근 제어는 웹 요청 단위로 보안을 적용하는 데 유용하지만, 더 세밀한 제어가 필요한 경우가 있습니다. 예를 들어, 특정 비즈니스 로직이나 서비스 메서드에 접근을 제한하고 싶을 때 메서드 수준 보안 설정을 사용합니다. 스프링 시큐리티는 이를 위해 메서드 호출 시점에서 권한을 검사하는 기능을 제공하며, 주로 어노테이션 기반으로 구현됩니다.

메서드 수준 보안의 필요성
  • 세밀한 제어: URL 패턴만으로는 컨트롤러 내부 메서드의 개별 로직을 구분하기 어렵습니다.
  • 비즈니스 로직 보호: 데이터베이스 작업이나 민감한 연산을 호출하는 메서드를 보호할 수 있습니다.
  • 재사용성: 여러 엔드포인트에서 호출되는 서비스 메서드에 일관된 보안을 적용할 수 있습니다.

스프링 시큐리티는 메서드 수준 보안을 활성화하려면 @EnableMethodSecurity를 설정 클래스에 추가해야 합니다. 이후 @PreAuthorize, @Secured 같은 어노테이션을 사용해 권한을 검사합니다.

기본 설정
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {
    // 다른 설정 (UserDetailsService, SecurityFilterChain 등) 생략
}

@EnableMethodSecurity는 메서드 보안을 활성화하며, 기본적으로 @PreAuthorize, @PostAuthorize, @Secured 어노테이션을 지원합니다.

5.4 @PreAuthorize와 @Secured 활용

스프링 시큐리티는 메서드 수준 보안을 위해 두 가지 대표적인 어노테이션을 제공합니다: **@Secured**와 @PreAuthorize. 두 어노테이션은 비슷한 목적을 가지지만, 사용법과 유연성에서 차이가 있습니다.

@Secured 어노테이션

@Secured는 메서드에 접근할 수 있는 역할(Role)을 지정하는 간단한 어노테이션입니다. 주로 역할 기반 접근 제어에 사용되며, 설정이 직관적입니다.

사용 예제
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;

@Service
public class AdminService {

    @Secured("ROLE_ADMIN")
    public String manageUsers() {
        return "User management page for admins only";
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public String viewProfile() {
        return "Profile visible to users and admins";
    }
}
  • @Secured("ROLE_ADMIN"): ROLE_ADMIN 역할이 있는 사용자만 manageUsers() 메서드를 호출할 수 있습니다.
  • @Secured({"ROLE_USER", "ROLE_ADMIN"}): ROLE_USER 또는 ROLE_ADMIN 중 하나라도 가진 사용자가 viewProfile()를 호출할 수 있습니다.
동작 원리
  1. 메서드 호출 시 스프링 시큐리티의 AOP(Aspect-Oriented Programming) 프록시가 개입합니다.
  2. 현재 인증된 사용자의 GrantedAuthority 목록을 확인해 지정된 역할이 있는지 검사합니다.
  3. 역할이 없으면 AccessDeniedException이 발생하고, 호출이 차단됩니다.
한계
  • 역할만 지원하며, 권한(Authority)이나 복잡한 조건은 처리 불가.
  • SpEL(Spring Expression Language)을 지원하지 않아 유연성이 제한적.
@PreAuthorize 어노테이션

@PreAuthorize@Secured보다 더 강력하고 유연한 어노테이션으로, SpEL을 사용해 복잡한 조건을 정의할 수 있습니다. 역할, 권한, 메서드 매개변수, 인증 객체 등을 기반으로 접근을 제어할 수 있습니다.

사용 예제
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class PostService {

    @PreAuthorize("hasRole('ADMIN')")
    public String deleteAllPosts() {
        return "All posts deleted by admin";
    }

    @PreAuthorize("hasAuthority('WRITE_POST')")
    public String createPost(String content) {
        return "Post created: " + content;
    }

    @PreAuthorize("#username == authentication.name")
    public String viewOwnProfile(String username) {
        return "Profile for " + username;
    }

    @PreAuthorize("hasRole('USER') and #postId > 0")
    public String editPost(int postId, String content) {
        return "Post " + postId + " updated: " + content;
    }
}
  • hasRole('ADMIN'): ROLE_ADMIN 역할 검사. (@Secured와 유사하지만 SpEL 사용 가능)
  • hasAuthority('WRITE_POST'): WRITE_POST 권한 검사.
  • #username == authentication.name: 메서드 매개변수(username)가 현재 인증된 사용자의 이름과 같은지 확인.
  • hasRole('USER') and #postId > 0: ROLE_USER 역할이 있고, postId가 양수일 때만 허용.
동작 원리
  1. @PreAuthorize는 메서드 실행 전에 SpEL 표현식을 평가합니다.
  2. 표현식이 true면 메서드가 실행되고, falseAccessDeniedException이 발생합니다.
  3. authentication 객체(현재 사용자 정보)와 메서드 매개변수를 활용해 동적 조건을 검사합니다.
장점
  • 유연성: 역할, 권한, 매개변수 기반의 복잡한 로직 가능.
  • 조건문: and, or, not 같은 연산자 사용 가능.
  • 커스터마이징: SpEL을 통해 비즈니스 로직에 맞춘 조건 설정 가능.
@Secured vs @PreAuthorize 비교
특징 @Secured @PreAuthorize
지원 범위 역할(Role)만 역할, 권한, SpEL 조건
유연성 낮음 높음
사용 난이도 간단 약간 복잡
예제 @Secured("ROLE_ADMIN") @PreAuthorize("hasRole('ADMIN') and #id > 0")
실습 예제
  1. 컨트롤러에 @Secured("ROLE_USER")를 추가해 특정 엔드포인트 보호.
  2. 서비스 메서드에 @PreAuthorize("#id == authentication.principal.username")를 적용해 사용자 본인의 데이터만 수정 가능하도록 설정.
  3. ROLE_ADMINMANAGE_USERS 권한을 가진 사용자로 로그인해 두 어노테이션의 동작 확인.
주의사항
  • 성능: 메서드 수준 보안은 AOP 프록시를 통해 동작하므로, 과도한 사용은 성능에 영향을 줄 수 있습니다.
  • 예외 처리: AccessDeniedException을 적절히 핸들링해 사용자 친화적인 오류 메시지를 제공하세요.
  • 설정 활성화: @EnableMethodSecurity가 없으면 어노테이션이 동작하지 않으니 반드시 추가하세요.

위 내용은 메서드 수준 보안의 필요성과 @Secured, @PreAuthorize 어노테이션의 활용 방법을 체계적으로 설명했습니다. 추가 예제나 특정 상황에 대한 설명이 필요하면 말씀해 주세요!