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()를 호출할 수 있습니다.
동작 원리
- 메서드 호출 시 스프링 시큐리티의 AOP(Aspect-Oriented Programming) 프록시가 개입합니다.
- 현재 인증된 사용자의
GrantedAuthority목록을 확인해 지정된 역할이 있는지 검사합니다. - 역할이 없으면
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가 양수일 때만 허용.
동작 원리
@PreAuthorize는 메서드 실행 전에 SpEL 표현식을 평가합니다.- 표현식이
true면 메서드가 실행되고,false면AccessDeniedException이 발생합니다. authentication객체(현재 사용자 정보)와 메서드 매개변수를 활용해 동적 조건을 검사합니다.
장점
- 유연성: 역할, 권한, 매개변수 기반의 복잡한 로직 가능.
- 조건문:
and,or,not같은 연산자 사용 가능. - 커스터마이징: SpEL을 통해 비즈니스 로직에 맞춘 조건 설정 가능.
@Secured vs @PreAuthorize 비교
| 특징 | @Secured |
@PreAuthorize |
|---|---|---|
| 지원 범위 | 역할(Role)만 | 역할, 권한, SpEL 조건 |
| 유연성 | 낮음 | 높음 |
| 사용 난이도 | 간단 | 약간 복잡 |
| 예제 | @Secured("ROLE_ADMIN") |
@PreAuthorize("hasRole('ADMIN') and #id > 0") |
실습 예제
- 컨트롤러에
@Secured("ROLE_USER")를 추가해 특정 엔드포인트 보호. - 서비스 메서드에
@PreAuthorize("#id == authentication.principal.username")를 적용해 사용자 본인의 데이터만 수정 가능하도록 설정. ROLE_ADMIN과MANAGE_USERS권한을 가진 사용자로 로그인해 두 어노테이션의 동작 확인.
주의사항
- 성능: 메서드 수준 보안은 AOP 프록시를 통해 동작하므로, 과도한 사용은 성능에 영향을 줄 수 있습니다.
- 예외 처리:
AccessDeniedException을 적절히 핸들링해 사용자 친화적인 오류 메시지를 제공하세요. - 설정 활성화:
@EnableMethodSecurity가 없으면 어노테이션이 동작하지 않으니 반드시 추가하세요.
위 내용은 메서드 수준 보안의 필요성과 @Secured, @PreAuthorize 어노테이션의 활용 방법을 체계적으로 설명했습니다. 추가 예제나 특정 상황에 대한 설명이 필요하면 말씀해 주세요!