使用Autoproxy在AspectJ模式下无法使用@Secured注释

Ric*_*ell 1 java spring aspectj spring-security

我正在尝试使用Spring @Secured注释和AspectJ自动代理来使用我的Spring MVC应用程序,但它似乎没有代理或识别我的@Secured注释.我有一个像这样的控制器:

@Controller
@RequestMapping("/")
public class ApplicationController {

    private ApplicationFactory applicationFactory;

    @Inject
    public ApplicationController(ApplicationFactory applicationFactory) {
        super();
        this.applicationFactory = applicationFactory;
    }

    @Secured("ROLE_USER")
    @ResponseBody
    @RequestMapping(method = GET)
    public Application getApplicationInfo() {
        return applicationFactory.buildApplication(this);
    }

}
Run Code Online (Sandbox Code Playgroud)

一个Spring安全XML看起来像这样:

码:

  <security:global-method-security secured-annotations="enabled" mode="aspectj" proxy-target-class="true" />

  <security:http auto-config="true" use-expressions="true">
    <security:http-basic/>
  </security:http>
Run Code Online (Sandbox Code Playgroud)

上面是由no-xml Spring @Configuration组件加载的,如下所示:

@Configuration
@ComponentScan(basePackages = {"com.example"})
@EnableWebMvc
@ImportResource("classpath:security.xml")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {

}
Run Code Online (Sandbox Code Playgroud)

反过来使用Servlet 3.0 WebApplicationInitializer加载:

public class SpringMvcInitializer implements WebApplicationInitializer {

    private final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();

    public void onStartup(ServletContext servletContext) throws ServletException {
        context.register(ApplicationConfiguration.class);

        servletContext.addListener(new ContextLoaderListener(context));
        servletContext.addListener(new Log4jConfigListener());

        final DelegatingFilterProxy proxy = new DelegatingFilterProxy("springSecurityFilterChain", context);
        FilterRegistration.Dynamic filter = servletContext.addFilter("securityFilter", proxy);
        filter.addMappingForUrlPatterns(EnumSet.of(REQUEST), false, "/*");

        final DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/*");
    }

}
Run Code Online (Sandbox Code Playgroud)

但是,Spring Security没有检测到注释,我仍然可以在未经授权的情况下使用上面的安全端点.根据Spring Security FAQ,这可能是因为<global-method-security>元素是在错误的应用程序上下文中加载的,但我不知道如何使用上面的no-xml Spring配置来确保它.

我错过了什么吗?我尝试将@EnableAspectJAutoProxy(proxyTargetClass = true)添加到我的应用程序配置中,但这也没有帮助.无论如何都有运行时编织或者我是否必须使用编译时编织来为我的应用程序启用基于注释的安全性?

axt*_*avt 5

在Spring中使用AOP时,您可以选择两种AOP实现:

  • Spring AOP实现不需要编织,但它只适用于Spring管理的bean并且有一些限制

  • AspectJ AOP实现可以适用于所有对象,并且没有Spring AOP的限制,但需要编译时或加载时编织

mode="aspectj" 告诉Spring使用AspectJ进行AOP实现,因此在没有编织的情况下安全方面将无法工作.

术语"的AspectJ自动代理"无关与使用AspectJ作为AOP实现 - 这是一项功能,允许您使用AspectJ的API(而不是实现)Spring AOP实现.

因此,在您的情况下,您可以使用Spring AOP实现,因为控制器是一个Spring bean,因此您应该删除mode="aspectj".另请注意,您的控制器应该具有无参数构造函数 - 这是Spring AOP的限制之一.