引入Spring Security后,在Controller的方法中会出现Spring Security的方法注解与AOP同时存在的问题,这是就会设计顺序问题
@Controller
public class HelloController{
@RequestMapping(value = "/hello")
@BeforeController
@PreAuthorize("validate(#user)")
public void hello(@RequestParam("user) String user) {
// 业务代码
}
}
上述Controller中@BeforeController
是一个业务AOP,@PreAuthorize
是来授权校验user。按照业务逻辑,执行顺序应该是如下:
但实际是@BeforeController
在@PreAuthorize
之前。
其实@PreAuthorize
也是依赖于AOP实现,当多个AOP在一个方法上时就会有顺序问题。在Aop中指定顺序的方法有:
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeforeController {
}
- 1、
@Order
注解@Aspect @Component @Order(0) public class BeforeControllerAction { @Before("@annotation(org.numb.web.aop.BeforeController)") public void before(final JoinPoint joinPoint) { // before切面业务代码 } }
@Order
注解里面的值是一个整数,数值越大优先级越低,默认是Integer.MIN_VALUE
,即最低优先级。 - 2、实现
org.springframework.core.Ordered
接口@Aspect @Component public class BeforeControllerAction implements Ordered { @Before("@annotation(org.numb.web.aop.BeforeController)") public void before(final JoinPoint joinPoint) { // before切面业务代码 } @Override public int getOrder() { return 0; } }
- 3、通过配置文件配置顺序
<aop:config expose-proxy="true"> <aop:pointcut id="beforeController" expression="@annotation(org.numb.web.aop.BeforeController)"/> <aop:aspect ref="beforeControllerAction" id="beforeControllerAction"> <aop:before method="before" pointcut-ref="beforeController"/> </aop:aspect> </aop:config>
而Spring Security的执行顺序本质上也是由AOP决定,可以通过指定order的方式确定:
@EnableGlobalMethodSecurity(order = 0)
查看源码可见
public @interface EnableGlobalMethodSecurity {
...
/**
* Indicate the ordering of the execution of the security advisor when multiple
* advices are applied at a specific joinpoint. The default is
* {@link Ordered#LOWEST_PRECEDENCE}.
* @return the order the security advisor should be applied
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}