I'm trying to get my Spring MVC app to play nice with Spring @Secured annotations and AspectJ auto-proxying but it doesn't seem to be proxying or recognising my @Secured annotations. I have a controller like this:
@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);
}
}
And a spring security XML that looks something like this:
Code:
<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>
The above is being loaded by a no-xml Spring @Configuration component like this:
@Configuration
@ComponentScan(basePackages = {"com.example"})
@EnableWebMvc
@ImportResource("classpath:security.xml")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
}
Which in turn is loaded using a 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("/*");
}
}
However, Spring Security isn't detecting the annotation and I'm still able the secured endpoint above without being authorised. According to the Spring Security FAQ, this maybe because the <global-method-security>
element is being loaded in the wrong application context, but I don't know how to ensure this using the above no-xml Spring configuration.
Am I missing something? I tried adding the @EnableAspectJAutoProxy(proxyTargetClass = true) to my application configuration but that didn't help either. Is there anyway to have run time weaving or will I have to use compile time weaving to enable annotation-based security for my application?