-
Notifications
You must be signed in to change notification settings - Fork 26
4. Method Security Expression
본 페이지는 스프링 시큐리티가 지원하는 메소드 보안 표현식에 대해서 설명합니다.
스프링 시큐리티 3.0+부터 Spring EL
표현식을 사용해 권한 부여 매커니즘을 적용할 수 있습니다. 표현식 기반의 접근 제어는 동일한 아키텍처를 기반으로 하지만 복잡한 Boolean 로직을 단일 표현식으로 캡슐화 합니다.
SecurityExpressionRoot
는 최상위 표현식 오브젝트를 위한 기초 클래스입니다. 이 클래스는 웹 과 메소드 보안에 사용할 수 있는 몇가지 일반 표현식을 제공합니다.
Table 1. 일반 내장 표현식
표현식 | 설명 |
---|---|
hasRole(String role) |
현재 인증 주체가 특정 롤을 가지면 true 를 리턴합니다. 예를 들어, hasRole('admin') 기본적으로 적용된 롤이 'ROLE_'로 시작하지 않으면 'ROLE_'이 앞에 추가됩니다. DefaultWebSecurityExpressionHandler 의 defaultRolePrefix 를 수정해서 커스터마이징 할 수 있습니다. |
hasAnyRole(String... roles) |
현재 인증 주체가 적용된 롤들 중에서 하나 이상을 가지면 true 를 리턴합니다. 예를 들어, hasAnyRole('admin', 'user')
|
hasAuthority(String authority) |
현재 인증 주체가 특정 권한을 가지면 true 를 리턴합니다. 예를 들어, `hasAuthority('read') |
hasAnyAuthority(String... authorities) |
현재 인증 주체가 적용된 권한 중에서 하나 이상을 가지만 true 를 리턴합니다. 예를 들어, hasAnyAuthority('read', 'write')
|
principal |
현재 사용자를 표현하는 인증 주체 오브젝트에 직접적으로 접근할 수 있습니다. |
authentication |
SecurityContext 으로부터 현재 Authentication 오브젝트를 얻어 직접적으로 접근할 수 있습니다. |
permitAll |
항상 true 로 평가합니다. |
denyAll |
항상 false 로 평가합니다. |
isAnonymous() |
현재 인증 주체가 익명의 사용자인 경우 true 를 리턴합니다. |
isRememberMe() |
현재 인증 주체가 리멤버-미 사용자인 경우 true 를 리턴합니다. |
isAuthenticated() |
현재 사용자가 익명이 아닌 경우 true 를 리턴합니다. |
isFullyAuthenticated() |
현재 사용자가 익명이 아니거나 리멤버-미 사용자이면 true 를 리턴합니다. |
hasPermission(Object target, Object permission) |
현재 사용자가 주어진 퍼미션에 대해 제공된 타겟에 접근할 수 있으면 true 를 리턴합니다. hasPermission('domainObject', 'read')
|
hasPermission(Object targetId, String targetType, Object permission) |
현재 사용자가 주어진 퍼미션에 대해 제공된 타겟에 접근할 수 있으면 true 를 리턴합니다. hasPermission(1, 'com.example.domain.Message', 'read')
|
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('admin') and hasIpAddress('192.168.1.0/24')");
}
"admin" 영역("/admin/**")을 "admin" 롤이 부여된 사용자이면서 IP주소가 로컬 서브넷과 일치하여야 사용할 수 있도록 정의했습니다.
표현식 hasIpAddress
는 웹 보안에서 사용할 수 있는 추가 내장 표현식입니다. 이 표현식은 WebSecurityExpressionRoot
클래스에 정의되어 있습니다. 이 오브젝트는 HttpServletRequest
객체를 직접 노출하여 표현식에서 request
를 직접적으로 호출할 수 있습니다. 표현식을 사용하면 AccessDecisionManager
에 WebExpressionVoter
가 추가됩니다.
사용 가능한 표현식을 확장하고싶은 경우 공개된 모든 Spring Bean을 쉽게 참조할 수 있습니다. 예를 들어, 다음의 메소드 시그니처를 포함하는 webSecurity
이름의 빈을 가진다고 가정합시다.
public class WebSecurity {
public boolean check(Authentication authentication, HttpServletRequest request) {
...
}
}
함수를 사용해서 참조할 수 있습니다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/**").access("@webSecurity.check(authentication, httpServletRequest)");
}
때때로는 URL 안에 있는 경로 변수를 참조하는게 좋을 수 있습니다. 예를 들어, RESTful 애플리케이션이 /users/{userId}
경로에서 사용자 ID로 사용자를 찾는다면 패턴에 위치한 경로 변수를 쉽게 참조할 수 있습니다.
public class WebSecurity {
public boolean checkUserId(Authentication authentication, long id) {
return false;
}
}
checkUserId 메소드로 매치된 경로 변수를 제공합니다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/{userId}").access("@webSecurity.checkUserId(authentication, #userId)");
}
메소드 보안은 간단한 허용 또는 거부 규칙보다 조금 더 복잡합니다. 스프링 시큐리티 3.0+는 포괄적인 표현식 사용을 위해서 몇가지 새로운 어노테이션을 소개했습니다.
가장 명백하게 유용한 어노테이션은 @PreAuthorize
로 메소드를 실제로 호출할 수 있는지 여부를 결정합니다. 예를 들어,
@PreAuthorize("hasRole('USER')")
public void create(Contact contact);
이 의미는 "ROLE_USER" 롤을 가진 사용자만 접근을 허용한다는 의미입니다.
모든 Spring EL 기능은 표현식 내에서 사용가능하므로 매개변수의 프로퍼티에 접근할 수 있습니다. 예를 들어, 사용자의 연락처와 일치하는 사용자만 접근을 허용하는 어떤 함수가 있다면
@PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact);
예를 들어, 게시물의 작성자와 현재 인증 주체가 동일한지 비교할 수 있겠네요
메소드 보안을 위해 메타 어노테이션을 사용해서 코드를 더 읽기 쉽게 만들 수 있습니다. 이는 특히 코드 베이스 전체에서 동일하게 사용하는 복잡한 표현식의 반복에 편리합니다. 예를 들어,
@PreAuthorize("#contact.name == authentication.name")
모든 곳에서 반복하는 것 대신에 메타 어노테이션을 만들어서 대신 사용할 수 있습니다.
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("#contact.name == authentication.name")
public @interface ContactPermission {}
메소드에 대한 보안을 지원하기 위해서 스프링 시큐리티가 2.0+ 부터 추가된 보안 적용 방식입니다. @Secured
어노테이션으로 알려진 JSR-250
어노테이션에 대한 지원을 제공합니다. 또한, 3.0+부터는 새로운 표현식 기반의 어노테이션을 추가했습니다.
@Configuration
인스턴스에 @EnableGlobalMethodSecurity
를 사용해서 어노테이션 기반의 보안을 활성화 할 수 있습니다.
- securedEnabled :
@Secured
어노테이션을 활성화 합니다. - jsr250Enabled : JSR-250 어노테이션을 활성화합니다.
- prePostEnabled : Spring Security의 기본 어노테이션을 활성화합니다.
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = false)
@Configuration(proxyBeanMethods = false)
public class GlobalMethodSecurityConfig {
}
@EnableGlobalMethodSecurity
어노테이션이 허용하는 것보다 더 복잡하게 수행하기 위해서 GlobalMethodSecurityConfiguration를 확장
할 수 있습니다.
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = false)
@Configuration(proxyBeanMethods = false)
public class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
// ... create and return custom MethodSecurityExpressionHandler ...
return expressionHandler;
}
}