전역 메서드 보안 (Global Method Security)
- 클래스나 메서드 단위에서 특정 권한을 가진 사용자만 메서드를 실행하도록 제한할 수 있는 기능
- 전역 메서드 보안에서 수행할 수 있는 두 가지 주요 작업은 다음과 같음
- 호출 권한 부여
- 필터링
- 기본적으로 스프링 시큐리티에서는 전역 메서드 보안이 비활성화 상태로 제공되기 때문에 해당 기능을 사용하기 위해서는 전역 메서드 보안을 우선 활성화해줘야 함
- Spring Security 6 버전에서는 @EnableMethodSecurity 하위 버전에서는 @EnableGlobalMethodSecurity 어노테이션 부여
- 전역 메서드 보안을 활성화시키면 스프링의 Aspect(보안 Aspect)가 하나 활성화 됨
- 해당 Aspect는 호출을 가로채어 권한 부여 규칙이 충족되지 않으면 서비스로 호출을 제한함

1. 호출 권한 부여
- 특정 메서드가 실행되기 전, 현재 사용자에게 해당 메서드를 실행할 권한이 있는지를 검사하는 것을 의미
- 특정 메서드가 호출되기 전, 사용자의 인증 정보나 권한을 검증하여 메서드 실행을 허용하거나 차단할 수 있음
- 메서드에 제공된 파라미터에 따라 접근할 수 있는지 여부를 판단 가능
- 메서드의 결과에 따라 어떠한 결정을 해야 할 때 이를 활용 가능
- 호출 권한 부여는 다음과 같이 크게 두 가지로 분류
- 사전 권한 부여(PreAuthorization): 메서드 호출 전 권한 부여 규칙을 검사하는 프레임워크
- 사후 권한 부여(PostAuthorization): 메서드 호출 후 권한 부여 규칙을 검사하는 프레임워크
1.1 사전 권한 부여
- 메서드가 실행되기 전에 현재 사용자(또는 인증된 사용자)의 권한을 검사하는 방식
- Spring Security는 메서드가 호출되기 전에 사용자의 권한을 확인하고, 해당 권한이 충분하지 않으면 메서드를 실행하지 않고 예외를 발생시킴
- 이를 통해, 특정 메소드에 대해 특정 사용자만 접근할 수 있도록 제한할 수 있음
- @PreAuthorize 어노테이션은 주로 이 기능을 구현하는 데 사용되며, 권한, 역할, 사용자 소유권 등을 검사하여 권한을 부여
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@PreAuthorize("hasRole('ADMIN')") | |
public void performAdminTask() { | |
// 관리자만 수행할 수 있는 작업 | |
} | |
@PreAuthorize("#userId == authentication.principal.id") | |
public void updateProfile(Long userId) { | |
// 사용자는 자신의 프로필만 수정 | |
} |
1.2 사후 권한 부여
- 메서드가 실행된 후, 반환된 결과를 기반으로 접근 권한을 검사하는 방식
- 메서드가 먼저 실행된 후, 반환된 객체나 데이터가 특정 조건을 충족하는지 검사한 후에 사용자에게 결과를 반환할지 여부를 결정
- @PostAuthorize 애너테이션은 사후 권한 부여를 구현하는 데 사용되며, 반환된 값에 대한 검증을 수행
- 메서드의 로직이 어떤 상태를 변경하는 WRITE, MODIFY, DELETE 같은 기능을 포함하고 있을 경우 멱등성을 보장하지 못할 수 있기 때문에 주의 필요
- 권한이 유효하지 않아 예외가 던져지더라도 메서드 혹은 데이터에 대한 롤백은 따로 진행되지 않음
- 사후 권한 부여 기능에서 발생하는 예외는 트랜잭션이 커밋된 이후에 발생하는 것이기 때문에 @Transactional 어노테이션을 부여하더라도 제대로 동작하지 않을 수 있음
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@PostAuthorize("returnObject.owner == authentication.name") | |
public User getUserProfile(Long userId) { | |
// 메소드 실행 후, 반환된 User 객체의 소유자가 현재 사용자와 일치하는지 확인 | |
return userService.findUserById(userId); | |
} | |
@PostAuthorize("returnObject.isPublic() or returnObject.owner == authentication.name") | |
public Document getDocumentById(Long documentId) { | |
// 문서가 공개 상태이거나 소유자와 일치하는 경우에만 반환 | |
return documentService.findDocumentById(documentId); | |
} |
2. 필터링
- 리스트나 컬렉션과 같은 다수의 데이터가 반환될 때, 사용자의 권한에 따라 일부 데이터만 필터링하여 반환 가능
- 필터링 방식은 @PreFilter 및 @PostFilter 어노테이션을 사용하여 구현 가능
- @PreFilter: 메서드 실행 전에 전달된 데이터 리스트를 필터링
- @PostFilter: 메서드 실행 후 반환된 결과 리스트를 필터링
2.1 사전 필터링
- 메서드가 실행되기 전에, 메소드에 전달된 인수 중에서 특정 권한에 맞는 데이터만 메서드로 전달되도록 필터링하는 작업
- 메서드가 실행되기 전에 입력 데이터 중에서 사용자가 접근할 수 있는 데이터만 메서드로 전달됨
- 파라미터나 반환 결과값이 규칙을 준수하지 않아도 메서드 호출은 그대로 발생
- 예외를 던지지 않음
- 단, 조건에 맞지 않는 파라미터나 반환 결괏값을 필터링함
- 필터링의 개념이기 때문에 컬렉션이나 배열에서만 활용 가능
- 메서드가 구현하는 비즈니스 로직과 권한 부여 규칙을 분리할 수 있다는 장점이 있음
- @PreFilter 어노테이션은 메서드에 전달되는 컬렉션이나 배열 등의 데이터에 대해 필터링을 적용하여, 특정 조건을 만족하는 데이터만 메서드에 전달
- Spring Expression Language(SpEL)을 사용해 필터링 조건을 설정할 수 있으며, 필터링된 데이터만 메서드 내부에서 처리
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@PreFilter("filterObject.owner == authentication.name") | |
public void processDocuments(List<Document> documents) { | |
// 소유자가 현재 사용자와 일치하는 문서만 처리 | |
documents.forEach(document -> { | |
// 처리 로직 | |
}); | |
} |
주의: 필터링 개념이기 때문에 컬렉션은 추가/삭제가 가능한 MutableList 형태여야 함
2.2 사후 필터링
- 메서드가 실행된 후, 반환된 결과 데이터 중에서 사용자 권한에 맞는 데이터만 필터링하여 반환하는 작업
- 메서드가 실행된 후 결괏값이 클라이언트로 반환되기 전에 필터링이 이루어져, 사용자가 접근할 수 없는 데이터는 결괏값에서 제거
- 민감한 데이터나 접근이 제한된 데이터를 클라이언트에 노출하지 않도록 처리 가능
- @PostFilter 어노테이션은 메서드가 반환하는 컬렉션이나 배열 등의 데이터에 대해 필터링을 적용
- ex) ReactJS로 구현된 프런트엔드와 스프링으로 구현된 백엔드가 서로 연결되어 있다고 가정했을 때 프런트에서는 로그인된 사용자에 대한 데이터만 조회해야 하는 상황이지만 어떤 데이터가 존재하는지 모르는 상황
- 이에 따라 로그인된 정보를 백엔드로 전달하면 백엔드에서 알아서 필터링하여 프런트로 전달
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@PostFilter("filterObject.owner == authentication.name") | |
public List<Task> getTasks() { | |
// 현재 사용자가 소유한 작업만 반환 | |
return taskService.getAllTasks(); | |
} |
주의: @PostFilter를 사용하기 위해서는 인증된 사용자 정보와 전체 리스트가 필요하기 때문에 findAll()과 같은 메서드로 전체 리스트를 가져오게 될 텐데, 실무 수준에서는 데이터 양이 엄청날 수 있음
- 경우에 따라 OOM(Out Of Memory)가 발생할 수 도 있고 성능 관점에서 매우 비효율적인 방법
참고
반응형
'Spring > Spring Security' 카테고리의 다른 글
[9장] 필터 구현 (0) | 2025.05.31 |
---|---|
[Spring Security] CSRF & CORS (0) | 2024.10.08 |
[Spring Security] 필터 체인과 커스텀 필터 (0) | 2024.10.08 |
[Spring Security] 액세스 제한과 권한 (0) | 2024.10.07 |
[Spring Security] 아키텍처 간단 정리 (0) | 2024.09.13 |