-
ch16 전역 메서드 보안 : 사전 및 사후 권한 부여IT 서적/Spring Security In Action 2024. 1. 11. 16:37
# 전역 메서드 보안 활성화
- 스프링 시큐리티에서는 웹 애플리케이션과 웹이 아닌 애플리케이션의 권한 부여를 구성할 수 있으며 이를 '전역 메서드 보안' 이라고 부른다.
- 방법은 크게 두 가지가 있다.
- 호출 권한 부여
- 필터링
# 호출 권한 부여의 이해
- 호출 권한 부여 방식은 메서드를 호출할 수 있는지를 결정하거나 메서드를 호출하도록 허용한 후 호출자가 메서드에서 반환된 값에 액세스할 수 있는지를 결정하는 권한 부여 규칙을 적용하는 것을 말한다.
- 전역 메서드 보안을 활성화하면 스프링 애스펙트 하나가 활성화된다.
- 이를 그림으로 나타내면 아래와 같다.
- 스프링 프레임워크의 구현은 상당수가 AOP(관점 지향 프로그래밍)에 의존한다.
- 전역 메서드 보안은 애스펙트에 의존하는 스프링 애플리케이션의 많은 구성 요소 중 하나다.
# 프로젝트에서 전역 메서드 보안 활성화
- 스프링 시큐리티에서 전역 메서드 보안은 기본적으로 활성화되지 않고 먼저 활성화해야 이용할 수 있지만 그 방법은 간단하며 구성 클레스에 @EnableGlobalMethodSecurity 어노테이션을 추가하면 된다.
- 전연 메서드 보안에는 권한 부여 규칙을 정의하는 세 가지 접근 방식이 있다.
- 사전/사후 권한 부여 어노테이션
- JSR 250 어노테이션(@RoleAllowed)
- @Secured 어노테이션
- 거의 모든 상황에 사전/사후 권한 부여 어노테이션을 이용하므로 이 방법에 대해서 알아보자.
- 이 접근 방식을 활성화하려면 @EnableGlobalMethodSecurity 어노테이션의 prePostEnabled 특성을 이용한다.
- 예제 소스는 아래와 같다.
- ProjectConfig 클레스
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class ProjectConfig { @Bean public UserDetailsService userDetailsService() { var service = new InMemoryUserDetailsManager() ; var u1 = User.withUsername("natalie") .password("12345") .authorities("read") .build() ; var u2 = User.withUsername("emma") .password("12345") .authorities("write") .build() ; service.createUser(u1); service.createUser(u2); return service ; } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance() ; } }
- Controller 클레스
@RestController public class HelloController { @Autowired private NameService nameService ; @GetMapping public String hello() { return "Hello, " + nameService.getName() ; } }
- Service 클레스@Service public class NameService { @PreAuthorize("hasAuthority('write')") public String getName() { return "Fantastico" ; } }
- 결과
# 사후 권한 부여 적용
- 메서드 호출 후에 권한 부여 규칙을 적용하고 싶다면 사후 권한 부여를 이용하면 된다.
- 메서드 실행은 허용하되 반환되는 내용을 검증하고 기준이 충족되지 않으면 호출자가 반환 값에 접근하지 못하게 할 수 있다.
- 스프링 시큐리티로 사후 권한 부여를 적용하려면 @PostAuthproze 어노테이션을 이용한다.
- 사용 방법은 아래와 같다.
@Service public class BookService { private Map<String, Employee> records = Map.of("emma", new Employee("Emma Thompson", List.of("Karamazov Brothers"), List.of("accountant", "reader")), "natalie", new Employee("Natalie Parker", List.of("Beautiful Paris"), List.of("researcher")) ) ; @PostAuthorize("returnObject.roles.contains('reader')") public Employee getBookDetails(String name) { return records.get(name) ; } }
- 실무에서 썼던 예시로는 아래와 같다.
- 첫번째 코드처럼 보안 컨텍스트의 authentication을 설정하고, 두번째 코드처럼 Method 위에 보안을 설정했다.
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(payload.getSysId(),null,roles); /** SET : Security Context Holder */ SecurityContextHolder.getContext().setAuthentication(upat);
@PreAuthorize("isAuthenticated() and hasRole('ROLE_C')")
- @RolesAllowed와 @Secured 어노테이션은 @PreAuthorize, @PostAuthorize 보다는 기능이 떨어지므로 실제 시나리오에서는 그리 많이 사용되지 않는다.
- 사용법은 아래와 같다.
@RolesAllowed("ROLE_ADMIN") public String getName() { return "ADMIN" ; } @Secured("ROLE_ADMIN") public String getName() { return "ADMIN" ; }
'IT 서적 > Spring Security In Action' 카테고리의 다른 글
ch19 리액티브 앱을 위한 스프링 시큐리티 (0) 2024.01.12 ch17 전역 메서드 보안: 사전 및 사후 필터링 (0) 2024.01.12 ch10 CSRF 보호와 CORS 적용 (0) 2024.01.08 ch09 필터 구현 (0) 2024.01.07 ch08 권한 부여 구성: 제한 적용 (0) 2024.01.04