I've been banging my head over this one for a while now. I've done everything I could in order to find an appropriate solution and followed a lot of Stackoverflow examples and solutions.
First, I'm using annotation based solution. When I annotate my services, prePostEnabled works, but not when I annotate the controllers, it doesn't. Also, even on my services, jsr250Enabled doesn't work.
I've found a lot of case closed by moving the annotation from the security config to the MVC config, which in my case doesn't work.
I've a setup that looks like this: https://github.com/spring-projects/spring-security-oauth-javaconfig/tree/master/samples/oauth2-sparklr
But I use Servlet 3.0 and doesn't have anything in my web.xml.
My SecurityInitializer looks like this:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
My MVC initializer looks like this:
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{WebSecurityConfig.class, MethodSecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{ApiPaths.API + "/*", "/res.jsp"};
}
My WebSecurity config is initialized like this:
@Configuration
@EnableWebSecurity
@ComponentScan(value = {"com.roler.res.**.server"}, excludeFilters = {
@Filter(type = FilterType.ASSIGNABLE_TYPE, value = SpringMvcConfig.class),
@Filter(type = FilterType.ASSIGNABLE_TYPE, value = MethodSecurityConfig.class),
@Filter(type = FilterType.REGEX, pattern = "com.xyz.*.controller.*")})
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
And my SpringMvcConfig is initialized like this:
@Configuration
@EnableWebMvc
@ComponentScan(value = "com.xyz.**.controller")
public class SpringMvcConfig extends WebMvcConfigurerAdapter {
If you have any ideas, I'm out of juice, Thanks!
The symptoms you describe make me think to a problem of proxying. Annotations works fine on service layer, because services generally implements interfaces, and Spring can easily use a JDK proxy to put the AOP authorizations.
But controllers generally do not implement interfaces. That's the reason why PreAuthorize annotation are more frequently used in service layer. IMHO, you'd better try to use URL pattern based authorization instead of PreAuthorize annotations on controller. The alternative would be to use target class proxying with CGLIB.
To use PreAuthorize
and JSR-250 annotations, you must
annotate you spring security configuration class with :
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
if you use anywhere else in your application Spring AOP with JDK proxies, make all controller classes in which you want to use method security implement interfaces declaring all protected methods
if you use anywhere else in your application Spring AOP with CGLIB proxies, add proxyTargetClass = true
to @EnableGlobalMethodSecurity
:
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true,
proxyTargetClass = true)
if you want to use CGLIB proxies with Spring version under 3.2, add CGLIB library to your classpath (CGLIB classes are included in Spring 3.2+)
But anyway, my advice is to try to move method security to service layer which normally already supports AOP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With