Spring Security 5.7.11 기준이다.
- 스프링 시큐리티에는 컨트롤러에 역할(Role) 기반 접근 제한을 설정하는 방법에 여러 가지가 있는데,
- 가장 일반적인 방법으로는 @PreAuthorize 또는 @Secured 어노테이션을 사용하는 것이다.
- 해당 어노테이션은 메서드 수준의 보안이 가능하다.
@PreAuthorize
- 특정 역할을 가진 사용 역할을 가진 사용자만 메서드를 호출할 수 있도록 제한할 수 있다.
@Controller public class SomeController { @PreAuthorize("hasRole('ROLE_ADMIN')") @RequestMapping("/adminOnly") public String adminOnly() { // 관리자만 접근 가능한 로직 return "admin"; } }
@PreAuthorize("hasAnyRole('ROLE_CUSTOMER', 'ROLE_ADMIN')") //OR 조건으로 역할을 제한 @GetMapping("/{orderId}") public ResponseEntity<OrderResponseDTO> getOrder(@PathVariable Long orderId) { OrderRequestDTO orderRequestDTO = OrderRequestDTO.forActiveOrder(orderId); return ResponseEntity.ok(orderService.getOrder(orderRequestDTO)); }
어노테이션 소스
package org.springframework.security.access.prepost; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation for specifying a method access-control expression which will be evaluated to * decide whether a method invocation is allowed or not. * * @author Luke Taylor * @since 3.0 */ @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface PreAuthorize { /** * @return the Spring-EL expression to be evaluated before invoking the protected * method */ String value(); }
- 타입
- 메서드와 타입(클래스, 인터페이스 등) 에 적용가능한 어노테이션입니다.
- 클래스 전체 또는 인터페이스
- Retention
- 어노테이션의 정보가 런타임시에도 유지되어야함.
- JVM이 클래스를 메모리에 로드하는 경우, 어노테이션의 정보가
런타임시에도 유지가
되어야 해당 권한에 따른 접근이 가능할 것이다
- Inherited
- 상속된 클래스가 부모 클래스의 PreAuthorize 어노테이션을 상속받을 수 있음.
- 해당 어노테이션이 부모 클래스에 적용된다면, 이를 상속받는 자식 클래스도 같은 보안 정책을 적용받게 되는 것입니다
- Documented
- javadoc 과 같은 문서에 포함 가능 ㅇㅇ
팁
- 어노테이션 내부의 value 메서드는
Spring Expression Language(SpEL)
표현식을 반환함.
- 메서드 호출 전에 평가되고, 표현식의 결과에 따라 메서드 호출 허용, 거부 결정
- 타입
@PostAuthorize
- PreAuthorize 와 거의 동일하다.
- 하지만, 권한 검사 이후 → 메서드 실행 → 그 이후의 권한을 검사할 필요가 있는 경우 해당 어노테이션을 사용한다.
- 예를 들어
- 사용자가 자신의 프로필 정보를 요청
- 해당 메서드가 사용자 정보를 반환시
@PostAuthorize
를 사용하여
- 반환된 사용자 정보가 요청한 사용자의 정보와 일치하는지를 확인이 가능하다.
- 사용자가 자신의 프로필 정보를 요청
@PostAuthorize("returnObject.email == authentication.email") // 리턴 객체의 이메일과 인증정보의 이메일 등을 비교가 가능함
- 예를 들어
@Secured
- SpEL 을 사용하지 않고, 단순히 역할을 문자로로만 사용한다.
import org.springframework.security.access.annotation.Secured; @Controller public class SomeController { @Secured("ROLE_ADMIN") @RequestMapping("/adminOnly") public String adminOnly() { // 관리자만 접근 가능한 로직 return "admin"; } }
- 소스
/** * Java 5 annotation for describing service layer security attributes. * * <p> * The <code>Secured</code> annotation is used to define a list of security configuration * attributes for business methods. This annotation can be used as a Java 5 alternative to * XML configuration. * <p> * For example: * * <pre> * @Secured({ "ROLE_USER" }) * public void create(Contact contact); * * @Secured({ "ROLE_USER", "ROLE_ADMIN" }) * public void update(Contact contact); * * @Secured({ "ROLE_ADMIN" }) * public void delete(Contact contact); * </pre> * @author Mark St.Godard */ @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Secured { /** * Returns the list of security configuration attributes (e.g. ROLE_USER, * ROLE_ADMIN). * @return String[] The secure method attributes */ String[] value(); }
- PreAuthorize 와 거의 동일하지만, SpEL 을 사용할 수 없기에, 별도 권한에 대한 조건을 걸기는 힘들다.
- 사실상 PreAuthrize 가 조금 더 실용적인 것 같다.
공식문서
Uploaded by N2T
'자바 > 리팩토링' 카테고리의 다른 글
@MybatisTest 클래스 레벨의 @Sql 이 수행되지 않는 경우 (0) | 2024.02.06 |
---|---|
[프로젝트] 모킹 클래스의 private 필드에 테스트 데이터 삽입 방법 - `ReflectionTestUtils` (0) | 2024.02.04 |
[프로젝트] RestDocs 커스텀 유저 모킹 `@MockMember` 적용기 (0) | 2024.02.02 |
[리팩토링] properties 파일을.. yaml 로 변경하면서 생긴, gradle 문제 해결 (0) | 2024.01.19 |
[리팩토링] Swagger UI + Spring RestDocs 적용기 (0) | 2024.01.05 |