1.前言欢迎阅读SpringSecurity实战干货系列文章。在上一篇文章基于配置的接口角色访问控制中,我们讲解了如何通过javaConfig配置接口角色访问控制。其实还有一种更灵活的基于注解的配置方式。今天就来说说吧。DEMO的获取方式在文末。2.SpringSecurity方法安全SpringSecurity基于注解的安全认证是通过在相关方法上标注安全注解来实现的。2.1启用全局方法安全我们可以在任何@Configuration实例上使用@EnableGlobalMethodSecurity注解来启用全局方法安全注解功能。这个注解提供了三种不同的机制来实现同一个功能,所以我们单独开一章来讨论。3.@EnableGlobalMethodSecurity注解@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)@Target(value={java.lang.annotation.ElementType.TYPE})@Documented@Import({GlobalMethodSecuritySelector.class})@EnableGlobalAuthentication@Configurationpublic@interfaceEnableGlobalMethodSecurity{/***基于表达式的方法访问控制*/booleanprePostEnabled()defaultfalse;/***基于@Secured注解*/booleansecuredEnabled()defaultfalse;/***基于JSR-250注解*/booleanjsr250Enabled()defaultfalse;booleanproxyTargetClass()defaultfalse;intorder()defaultOrdered.LOWEST_PRECEDENCE;}@EnableGlobalMethodSecurity在源码中提供了三个方法:prePostEnabled、securedEnabled和jsr250Enabled。当你启用全局基于注解的方法安全功能时,即使用@EnableGlobalMethodSecurity注解时,我们需要选择使用这三个中的一个或几个。接下来我们分别介绍。4.使用prePostEnabled如果在@EnableGlobalMethodSecurity中将prePostEnabled设置为true,则启用基于表达式的方法安全控制。是否访问由表达式运算结果的布尔值决定(true表示开放,false表示拒绝)。有时您可能需要在打开prePostEnabled的情况下执行复杂的操作。Fortheseinstances,youcanextendGlobalMethodSecurityConfiguration,ensuringthat@EnableGlobalMethodSecurity(prePostEnabled=true)ispresentonthesubclass.例如,如果要提供自定义MethodSecurityExpressionHandler:@EnableGlobalMethodSecurity(prePostEnabled=true)publicclassMethodSecurityConfigextendsGlobalMethodSecurityConfiguration{@OverrideprotectedMethodSecurityExpressionHandlercreateExpressionHandler(){//...createandreturncustomMethodSecurityExpressionHandler...returnexpressionHandler;}}上面的例子属于高级操作,一般没有必要。不管是否继承GlobalMethodSecurityConfiguration,都会启用四个注解。@PreAuthorize和@PostAuthorize侧重于方法调用的控制;而@PreFilter和@PostFilter专注于数据控制。4.1@PreAuthorize在标记的方法被调用之前,使用表达式计算是否可以授权访问。接下来,我将总结以下常用的表达方式。基于SecurityExpressionOperations接口的表达式,也就是我们上篇文章中的javaConfig配置。示例:@PreAuthorize("hasRole('ADMIN')")必须具有ROLE_ADMIN角色。基于UserDetails的表达式,用于对当前用户进行一些额外的限定操作。示例:@PreAuthorize("principal.username.startsWith('Felordcn')")只有用户名以Felordcn开头的用户才能访问。基于SpEL表达式对输入参数进行处理。SpEL表达式请参考官方文档。或关注公众号:Felordcn获取相关资讯。示例:@PreAuthorize("#id.equals(principal.username)")输入参数id必须与当前用户名相同。4.2@PostAuthorize标记的方法调用后,通过表达式计算是否可以授权访问。此注释用于@PreAuthorize。不同之处在于方法先执行。然后判断表情。如果该方法没有返回值,实际上等于开启了权限控制;如果有返回值,则实际结果是用户操作成功但没有收到响应。4.3@PreFilter根据方法入参相关的表达式过滤入参。谨慎使用分页!这个过程发生在接口接收参数之前。输入参数必须是java.util.Collection并且支持remove(Object)参数。如果有多个集合,则需要filterTarget=
