1. Introduction

Welcome to Spring Security’s hands-on dry goods series. In the previous article on Interface Role Access Control based on Configuration, we explained how to configure interface role access control using javaConfig. A more flexible configuration approach is based on annotations. Today we’re going to talk about it. Obtain DEMO at the end of this article.

2. Spring Security method Security

Spring Security’s annotation-based Security authentication is implemented by marking Security annotations on related methods.

2.1 Enabling Global Method Security

We can use @ EnableGlobalMethodSecurity comment on any of the @ Configuration instance method to enable global security annotations. This annotation provides three different mechanisms for implementing the same functionality, so we’ll discuss them in a separate chapter.

3. @ EnableGlobalMethodSecurity annotation

 @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
 @Target(value = { java.lang.annotation.ElementType.TYPE })
 @Documented
 @Import({ GlobalMethodSecuritySelector.class })
 @EnableGlobalAuthentication
 @Configuration
 public @interface EnableGlobalMethodSecurity {
 
 	/** * method access control based on expression */
 	boolean prePostEnabled(a) default false;
 
 	Based on the / * * *@SecuredNote * /
 	boolean securedEnabled(a) default false;
 
 	/** * Based on jSR-250 annotations */
 	boolean jsr250Enabled(a) default false;

 	boolean proxyTargetClass(a) default false;

 	int order(a) default Ordered.LOWEST_PRECEDENCE;
 }
Copy the code

@ EnableGlobalMethodSecurity source provides prePostEnabled, securedEnabled and jsr250Enabled in three ways. When you open the global method based on annotations security functions, namely using the @ EnableGlobalMethodSecurity annotations when we need to choose to use the three types of one or more of the following. We’ll look at each of them next.

4. Use prePostEnabled

If you’re @ EnableGlobalMethodSecurity set prePostEnabled to true, the open the safety control based on expression method. Access is determined by the Boolean value of the result of the expression operation (true open, false denied). Sometimes you may need to perform complex operations to enable prePostEnabled. For these instances, you can extend the GlobalMethodSecurityConfiguration, ensure that exists on the subclass @ EnableGlobalMethodSecurity (prePostEnabled = true). For example, if you want to provide custom MethodSecurityExpressionHandler:

 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
     @Override
     protected MethodSecurityExpressionHandler createExpressionHandler(a) {
         // ... create and return custom MethodSecurityExpressionHandler ...
         returnexpressionHandler; }}Copy the code

The above example is an advanced operation and is generally not necessary. Whether or not inheritance GlobalMethodSecurityConfiguration will open four notes. @preauthorize and @postauthorize focus on method invocation control; @prefilter and @Postfilter focus on data control.

4.1 @PreAuthorize

Before the tag’s method is called, the expression is used to evaluate whether access can be granted. Let me summarize the following commonly used expressions.

  • Based on theSecurityExpressionOperationsThe expression for the interface, which is where we areThe article,thejavaConfigConfiguration. Example:@PreAuthorize("hasRole('ADMIN')")Must have aROLE_ADMINRole.
  • Based on theUserDetailsIs used for some additional qualifying operations on the current user. Example:@PreAuthorize("principal.username.startsWith('Felordcn')")The user name starts withFelordcnUsers can access.
  • Based on the entry parameterSpELExpression processing. aboutSpELYou can refer to the official documentation for expressions. Or follow the public account “Felordcn” to get more information. Example:@PreAuthorize("#id.equals(principal.username)")The ginsengidIt must be the same as the current user name.

4.2 @PostAuthorize

After the method invocation of the tag, an expression is used to calculate whether access can be granted. This annotation is for @preauthorize. The difference is the method of execution first. Then the expression is judged. If the method does not return a value, it essentially opens permission control; If there is a return value, the actual result is that the user succeeded but got no response.

4.3 @PreFilter

Filter the input parameters based on the expression associated with the method input parameters. Paging with caution! This process occurs before the interface receives the parameters. The input parameter must be java.util.Collection and support the remove(Object) argument. If more than one collection needs to be specified by filterTarget=< Parameter name >. The built-in reserved name filterObject is used as the operation name of the collection element for evaluation filtering.

Sample:

Collection
      
        IDS test data ["Felordcn","felord","jetty"]
      

// Filter out felord jetty to Felordcn
@PreFilter(value = "filterObject.startsWith('F')",filterTarget = "ids")
// If the current user has ROLE_AD role parameters, otherwise the filter does not start with F
// DEMO users do not hold ROLE_AD roles, so only felord is left
@PreFilter("hasRole('AD') or filterObject.startsWith('f')")
Copy the code

4.4 @PostFilter

Unlike @prefilter, return values are filtered based on expressions associated with them. Paging with caution! This process occurs before the interface performs data return. The related tests are similar to @prefilter. See the DEMO at the end of this article.

5. Use securedEnabled

If you’re @ EnableGlobalMethodSecurity set securedEnabled is true, it opens the role annotation @ Secured, the annotation is much simple function, By default, access control decisions can only be made based on a set of roles (prefixed with ROLE_ by default).

The mechanism for this annotation is to be accessible as long as the set of roles (values) it declares contains any of the roles held by the current user. That is, the set of roles for the user and the set of roles for the @secured annotation must have a non-empty intersection. Decision making using SpEL expressions is not supported.

6. Use jsr250Enabled

Enable jsr-250 security control annotations, which are part of JavaEE’s security specification (now the Jakarta project). There are five security annotations. If you’re @ EnableGlobalMethodSecurity set jsr250Enabled is true, it opens the JavaEE security annotations in the following three:

  • @denyall denies all access
  • @permitall approves all access
  • @RolesAllowedUsage and5.In the@SecuredThe same.

7. To summarize

Today I’ve covered another static configuration of Spring Security based on annotations. Compared with javaConfig, the method is more flexible and granular, and SpEL expression can achieve more powerful functions. However, these two methods are static based on programming and have certain limitations. A more flexible approach is to dynamically handle the mapping between user roles and resources, which we will address in the future. The DEMO can be obtained by following the wechat official account: Felordcn reply ss09.

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn