스프링 시큐리티 (Spring Security) 속 메서드 시큐리티 (Method Security) 란?
- 애플리케이션 내부의 메서드 혹은 함수에 보안설정을 하는 것이다.
- 스프링 시큐리티에서 설정한 권한에 맞는 사용자만 해당 메서드를 사용할 수 있게 된다.
스프링 시큐리티 메서드를 구현하는 방법
- 보통 3가지 방법이 사용된다.
애노테이션 사용하기
@PreAuthorize
,@PostAuthorize
,@RolesAllowed
와 같은 메서드를 통해 구현할 수 있다.
표현식 사용하기
SpEL
(Spring Expression Language) 과 같은 표현식을 사용하여 가능하다.true
인지false
인지 결과값으로 권한이 평가된다.@PreAuthorize
,@PostAuthorize
와 같은 애너테이션으로 보안 제약을 더 걸수 있다.
AOP 이용하기
- 포인트컷 표현식으로 보안 제약을 줄 수 있다.
- 애플리케이션 전역에 거친 여러 메서드들에 제약을 줄 때 유용하다.
스프링 시큐리티 공식문서에서 말하는 - Method Security Overview
아래는 공식문서의 내용을 적절히 번역한 것이다.
- 스프링 시큐리티 2.0 이후 서비스 레이어 메서드에 추가적인 보안을 지원한다.
- 프레임워크의 원래 애노테이션인
@Secured
,@PreAuthorize
,@PostAuthorize
,@PreFilter
,@PostFilter
, JSR-250 Jakarta Annotation 을 제공한다. - 빈에 애노테이션을 적용하고
intercept-methods
엘리먼트를 이용하여 단일 빈에 보안을 적용할 수 있다. - AspectJ 스타일의 포인트컷을 이용하여 전체 서비스 레이어에 있는 빈에 보안을 적용할 수 있다.
@EnableGlobalMethodSecurity
@Configuration
인스턴스에@EnableMethodSecurity
애노테이션을 이용하면, 애노테이션을 기반으로 한 보안을 작동시킬 수 있다.prePostEnabled
,securedEnabled
,jsr250Enabled
등의 엘리먼트를 제공한다.- 원하는 것을
enabled
시켜서 보안을 적용할 수 있다.
- 원하는 것을
@Secured
애노테이션 예제
public interface BankService {
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account readAccount(Long id);
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")
public Account[] findAccounts();
@Secured("ROLE_TELLER")
public Account post(Account account, double amount);
}
@EnableGlobalMethodSecurity
에서securedEnabled
를true
로 설정하면 사용 가능하다.- Java 5 부터 메서드 보안을 위해 사용하던 애노테이션이다.
- 권한별 Authorization 을 도와준다.
@Pre...
그리고 @Post...
애노테이션
- 표현식의 attribute 를 지원한다.
- 표현식을 이용해 호출 전 후 권한 체크를 허용하고 제출된 아규먼트 혹은 리턴 값의 필터링도 지원한다.
@PreAuthorize
,@PreFilter
,@PostAuthorize
,@PostFilter
가 있다.
XML 에서는 아래와 같이 활성화한다.
<global-method-security pre-post-annotations="enabled"/>
@PreAuthorize
애노테이션
@PreAuthorize("hasRole('USER')")
public void create(Contact contact);
@PreAuthorize
는 권한을 체크하고 함수를 호출할지 말지 결정한다.
create()
메서드는"ROLE_USER"
를 가진 사용자에게만 허용되어있다.
@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);
- 위는 인자로 들어왔던
contact
정보를 활용하여, 권한 체크를 한다. - 표현식은 스프링 시큐리티 ACL 모듈과 연결되어 있어서
hasPermission()
과 같은 빌트인 표현식을 이용할 수 있다. @P
(스프링 시큐리티) 혹은@Param
(스프링 데이터) 애노테이션을 이용하면 커스텀한 이름을 사용해@PreAuthorize
의 표현식을 작성할 수도 있다.
import org.springframework.security.access.method.P;
@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);
@EnableMethodSecurity
@EnableMethodSecurity
는 스프링 시큐리티5.6
부터 사용할 수 있으며,@EnableGlobalMethodSecurity
의 향상된 버전이다.
- 메타 데이터 소스, 설정 애트리뷰트, decision managers, 그리고 voters 대신 간소화된
AuthorizationManager
API 를 사용한다. 이러한 것들이 재사용과 커스터마이징을 간단하게 해준다. - 빈을 커스터마이징하기 위해
GlobalMethodSecurityConfiguration
상속을 필요로 하기보다 빈을 기반으로 한 설정을 선호한다. - 추상을 제거하고 네이티브 스프링 AOP 를 이용해 만들어졌다. 커스터마이징할 수 있는 스프링 AOP 빌딩 블록을 사용하게 해준다.
- 모호한 보안 설정을 피하기 위해 애노테이션 충돌을 체크한다.
- JSR-250 과 함께 컴파일된다.
@PreAuthorize
,@PostAuthorize
,@PreFilter
,@PostFilter
를 기본으로 사용할 수 있게 해준다.
자주 쓰이는 Built-in expression 정리
org.springframework.security.access.expression.SecurityExpressionRoot
에서 살펴볼 수 있다.
hasRole(String role)
: 현재 Principal 이 Role 을 가지고 있다면,true
를 반환한다.ROLE_
로 시작하지 않으면, 자동으로 붙여준다.DefaultWebSecurityExpressionHandler
의defaultRolePrefix
를 수정하여 이 설정을 커스터마이징할 수 있다.hasAnyRole(String ...roles)
: 배열로 들어온 Role 중에 하나라도 가지고 있다면true
를 반환한다.hasAuthority(String authority)
: 현재 Principal 이 Authority 를 가지고 있다면,true
를 반환한다.hasAuthority(String ...authorities)
: 배열로 들어온 Authority 중에 하나라도 가지고 있다면,true
를 반환한다.principal
: 현재 유저를 표현하는 Principal 접근을 허용한다.authentcation
:SecurityContext
에서 가져온Authentication
에 접근할 수 있게 해준다.permitAll
:true
로 평가된다.denyAll
:false
로 평가된다.isAnonymous()
: 현재 Principal 이 익명의 유저라면,true
를 반환한다.isRememberMe()
: 현재 Principal 이remember-me
유저라면true
를 반화한다.isAuthenticated()
: 현재 Principal 이 익명의 유저가 아니라면,true
를 반환한다.isFullyAuthenticated()
: 익명의 유저가 아니거나, remember-me 유저가 아니라면,true
이다.hasPermission(Object target, Object permission)
: 사용자가 제공된 타겟에 대해 주어진 권한이 있다면,true
이다.hasPermission(Object targetId, String targetType, Object permission)
: 사용자가 제공된 타겟에 대해 주어진 권한이 있다면,true
이다. ex)hasPermission(1, 'com.example.domain.Message', 'read')
레퍼런스
현재 프로젝트에서 쓰는 버전은 5.3인데, 5.5에서 5.6버전을 넘어오면서 많은 변화가 생겨서 두 공식문서를 번갈아서 봐야 이해가 됐다.
반응형
'보안' 카테고리의 다른 글
스프링 시큐리티에서 Authority 와 Role 의 차이는? (2) | 2023.12.05 |
---|---|
리프레시 토큰 (refresh token) 을 사용하는 이유를 알아보자 (0) | 2022.10.13 |
CSRF 공격 정리 (feat. 스프링 시큐리티) (0) | 2022.05.03 |
JWT(Json Web Token) 이란 무엇이며 왜 사용하는가? (0) | 2022.05.03 |
인증 (Authentication) 과 인가 (Authorization) 의 차이를 알아보자. (0) | 2022.05.02 |