Spring Security is a Security framework that provides declarative secure access control solutions for Spring-based enterprise applications. It provides a set of beans that can be configured in a Spring application context, taking full advantage of Spring IoC,DI (Inversion of Control), and AOP (aspect oriented programming) capabilities. Provide declarative secure access control function for application system, reduce the work of writing a lot of repetitive code for enterprise system security control.

preface

Spring Security 3.0 has made it possible to control authorization using Spring EL expressions, allowing complex Boolean logic to be used in expressions to control access permissions.

Common expressions

The base class for the Spring Security available expression object is SecurityExpressionRoot.

expression describe
hasRole([role]) Returns true when the user has specified roles (Spring securityThe default isROLE_Prefix), remove referenceRemove the ROLE_
hasAnyRole([role1,role2]) Returns true if the user has any specified role
hasAuthority([authority]) Is equivalent tohasRoleBut not withROLE_The prefix
hasAnyAuthority([auth1,auth2]) Is equivalent tohasAnyRole
permitAll Always return true
denyAll Always return false
anonymous The current user isanonymousReturns true when
rememberMe The current champion isrememberMeUser returns true
authentication Of the current logged-in userauthenticationobject
fullAuthenticated The current user is neitheranonymousIs notrememberMeUser returns true
HasIpAddress (' 192.168.1.0/24 ')) Returns true if the sent IP addresses match

Part code:

.private String defaultRolePrefix = "ROLE_"; / / ROLE_ prefix

	/** Allows "permitAll" expression */
	public final boolean permitAll = true; / / all true

	/** Allows "denyAll" expression */
	public final boolean denyAll = false; / / all false
public final boolean permitAll(a) {
		return true;
	}

	public final boolean denyAll(a) {
		return false;
	}

	public final boolean isAnonymous(a) {
		// Whether it is anonymous
		return trustResolver.isAnonymous(authentication);
	}

	public final boolean isRememberMe(a) {
		// just rememberme
		returntrustResolver.isRememberMe(authentication); }...Copy the code

URL safe expression

onfig.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
                .anyRequest().authenticated();
Copy the code

Here we define the scope of the application /person/*URL, which is only valid for users with ADMIN or USER permissions.

Reference beans in Web security expressions

config.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
                .antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
                .anyRequest()
                .access("@rbacService.hasPermission(request,authentication)");
Copy the code
RbacServiceImpl
@Component("rbacService")
@Slf4j
public class RbacServiceImpl implements RbacService {
    /**
     * uri匹配工具
     */
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        log.info([RbacServiceImpl] --hasPermission={}", authentication.getPrincipal());
        Object principal = authentication.getPrincipal();

        boolean hasPermission = false;
        // It could be anonymous
        if (principal instanceof SysUser) {
            //admin always returns true
            if (StringUtils.equals("admin", ((SysUser) principal).getUsername())) {
                hasPermission = true;
            } else {
                // All urls that read user permissions return true here
                Set<String> urls = new HashSet<>();

                for (String url : urls) {
                    if (antPathMatcher.match(url, request.getRequestURI())) {
                        hasPermission = true;
                        break; }}}}return hasPermission;
    }

	  public boolean checkUserId(Authentication authentication, int id) {
        return true; }}Copy the code

The effect is as follows:

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/1/30/16147b3f89291c64~tplv-t2oaga2asx-image.image

Method security expression

For more complex access controls at the method level, Spring Security provides four annotations, @preauthorize, @prefilter, @postauthorize, and @postfilter

Use method annotations

  1. Enable the configuration of method-level annotations
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MerryyouSecurityConfig extends WebSecurityConfigurerAdapter {
Copy the code
  1. Configure the appropriate beans
 @Bean
    @Override
    public AuthenticationManager authenticationManagerBean(a) throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    @ConditionalOnMissingBean(PasswordEncoder.class)
    public PasswordEncoder passwordEncoder(a){
        return new BCryptPasswordEncoder();
    }
Copy the code
  1. Use annotations on methods
 /** * query all personnel */
    @PreAuthorize("hasRole('ADMIN')")
    @ApiOperation(value = "Get the List of Persons", notes = "")
    @GetMapping(value = "/persons")
    public List<Person> getPersons(a) {
        return personService.findAll();
    }
Copy the code
PreAuthorize

The @preauthorize annotation is appropriate for authorization validation before entering a method

@PreAuthorize("hasRole('ADMIN')")
    List<Person> findAll(a);
Copy the code
PostAuthorize

The @postauthorize authorization is executed after the method is executed. It is appropriate to validate permissions with return values. Spring EL provides return objects that can be returnObject in the expression language.

@PostAuthorize("returnObject.name == authentication.name")
    Person findOne(Integer id);
Copy the code
PreAuthorize Filters parameters
// When multiple objects are annotated with filterTarget
@PreFilter(filterTarget="ids", value="filterObject%2==0")
   public void delete(List<Integer> ids, List<String> usernames) {... }Copy the code
PostFilter filters the returned results
 @PreAuthorize("hasRole('ADMIN')")
    @PostFilter("filterObject.name == authentication.name")
    List<Person> findAll(a);
Copy the code

The effect is as follows:

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-el02.gif

The code download

Download it from my Github, github.com/longfeizhen…