我正在尝试让我的Spring MVC应用程序与Spring @Secured注释和AspectJ自动代理一起使用,但它似乎不代理或识别我的@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);
}
}
Spring 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>
以上是由no-xml Spring @Configuration组件加载的,如下所示:
@Configuration
@ComponentScan(basePackages = {"com.example"})
@EnableWebMvc
@ImportResource("classpath:security.xml")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
}
反过来使用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("/*");
}
}
但是,Spring Security没有检测到注释,我仍然可以在未经授权的情况下使用上面的安全端点。根据{{3}},这可能是因为<global-method-security>
元素正在错误的应用程序上下文中加载,但我不知道如何使用上面的no-xml Spring配置来确保这一点。
我错过了什么吗?我尝试将@EnableAspectJAutoProxy(proxyTargetClass = true)添加到我的应用程序配置中,但这也没有帮助。无论如何都有运行时编织或者我是否必须使用编译时编织为我的应用程序启用基于注释的安全性?
答案 0 :(得分:5)
在Spring中使用AOP时,您可以选择两种AOP实现:
Spring AOP实现不需要编织,但它只适用于由Spring管理的bean并具有some limitations
AspectJ AOP实现可以适用于所有对象,并且没有Spring AOP的限制,但需要编译时或加载时编织
mode="aspectj"
告诉Spring使用AspectJ进行AOP实现,因此在没有编织的情况下,安全方面将无法工作。
术语“AspectJ自动代理”与使用AspectJ作为AOP实现无关 - 它是一个允许您在Spring AOP中使用AspectJ API(而不是实现)的功能。
因此,在您的情况下,您可以使用Spring AOP实现,因为controller是一个Spring bean,因此您应该删除mode="aspectj"
。另请注意,您的控制器应该具有无参数构造函数 - 这是Spring AOP的限制之一。
答案 1 :(得分:3)
为了扩展@ axtavt的答案,mode="aspectj"
中的global-method-security
选项明确要求您的代码与spring-security-aspects
模块中的AnnotationSecurityAspect
编织在一起。< / p>
有一些sample code表明它正在使用中。它只包含一个安全的bean和一些Junit测试,但代码是用AspectJ编译器编译的。 application context还显示了与添加名称空间支持(注释掉的bean)之前所需的内容相比有多简单。