스프링 시큐리티는 SpEL 표현식을 사용한다. 표현식 평가는 root object를 사용하여 평가된다. 스프링 시큐리티는 특정 클래스를 루트 객체로 사용하여 기본 제공 표현식을 제공하고 현재와 같은 엑세스 규칙을 제공한다.
SecurityExpressionRoot가 바로 표현식 루트 객체이다.
    | Expression | Description | 
|---|---|
| hasRole(String role) | 현재 principal이 지정된 role을 가지고 있으면 true를 반환한다. | 
| hasAnyRole(String… roles) | 현재 principal이 제공된 역할 중 하나라도 가지고 있으면 true를 반환한다. | 
| hasAuthority(String authority) | 현재 principal이 지정된 authority를 가지고 있으면 true를 반환한다. | 
| hasAnyAuthority(String… authorities) | 현재 principal이 제공된 authority들을 가지고 있으면 true를 반환한다. | 
| principal | 현재 사용자를 나타내는 principal 객체에 접근할 수 있다. | 
| authentication | SecurityContext에서 가져온 Authentication 객체에 직접 엑세스할 수 있다. | 
| permitAll | 항상 true를 반환 | 
| denyAll | 항상 false를 반환 | 
| isAnonymous() | 현재 사용자가 익명 사용자면 true를 반환한다. | 
| isRememberMe() | 현재 사용자가 remember-me 사용자면 true를 반환한다. | 
| isAuthenticated() | 현재 사용자가 익명도이 아니면 true를 반환한다. | 
| isFullyAuthenticated() | 현재 사용자가 익명도, rememer-me도 아니면 true를 반환한다. | 
| hasPermission(Object target, Object permission) | 사용자가 주어진 권한에 대해 제공된 대상에 접근할 수 있으면 true를 반환한다. ex) hasPermission(domainObject, ‘read’) | 
| hasPermission(Object targetId, String targetType, Object permission) | 사용자가 주어진 권한에 대해 제공된 대상에 접근할 수 있으면 true를 반환한다. ex) hasPermission(1, ‘com.example.domain.Message’, ‘read’). | 
public class WebSecurity {
		public boolean check(Authentication authentication, HttpServletRequest request) {
				...
		}
}
http
    .authorizeHttpRequests(authorize -> authorize
        .requestMatchers("/user/**").access(new WebExpressionAuthorizationManager("@webSecurity.check(authentication,request)"))
        ...
    )
public class WebSecurity {
		public boolean checkUserId(Authentication authentication, int id) {
				...
		}
}
http
	.authorizeHttpRequests(authorize -> authorize
		.requestMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
		...
	);
@PreAuthorize@PreFilter@PostAuthorize@PostFilterglobal-method-security를 설정해야 한다.<global-method-security pre-post-annotations="enabled"/>
가장 많이 사용되는 어노테이션은 @PreAuthorize으로 메서드가 호출될 수 있는지 없는지를 결정한다.
  @PreAuthorize("hasRole('USER')")
  public void create(Contact contact);
ROLE_USER에게만 위 메서드를 허용한다.아래 예제는 현재 사용자가 contant에 admin 권한을 가지고 있는지 검사한다.
  @PreAuthorize("hasPermission(#contact, 'admin')")
  public void deletePermission(Contact contact, Sid recipient, Permission permission);
hasPermission() 표현식은 Spring Security ACL 모듈에 연결된다.Spring Security는 여러 방법으로 메서드 argument를 확인할 수 있다.
DefaultSecurityParameterNameDiscover를 이용@P나 @Param 어노테이션을 통해 아래와 같이 사용할 수도 있다.  import org.springframework.security.access.method.P;
    
  @PreAuthorize("#c.name == authentication.name")
  public void doSomething(@P("c") Contact contact);
  import org.springframework.data.repository.query.Param;
    
  @PreAuthorize("#n == authentication.name")
  Contact findContactByName(@Param("n") String name);
authentication이 등장하는데 이는 Security Context 내부의 Authentication이다.UserDetails에도 principal 표현식으로 접근할 수 있다.@PostFilter 어노테이션을 사용하면 반환된 컬렉션 또는 맵을 반복하여 표현식이 거짓인 요소를 모두 제거한다.
  @PreAuthorize("hasRole('USER')")
  @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
  public List<Contact> getAll();
filterObject는 현재 컬렉션의 객체를 참조한다.Map이 반환 값인 경우 filterObject.key 또는 filterObject.value를 사용할 수 있다.hasPermission() 표현식은 자세히 살펴볼 필요가 있다.인터페이스에는 두 메서드가 있다.
  boolean hasPermission(Authentication authentication, Object targetDomainObject,
  							Object permission);
    
  boolean hasPermission(Authentication authentication, Serializable targetId,
  							String targetType, Object permission);
Authentication이 제공되지 않을 때를 제외하고 사용 가능한 표현식에 직접 매핑된다.hasPermission() 표현식을 사용하려면 애플리케이션 컨텍스트에서 PermissionEvaluator를 명시적으로 구성해야 한다.