Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Securing controller method with @RolesAllowed and @PreAuthorize

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!

like image 875
Christian Goudreau Avatar asked Feb 12 '23 13:02

Christian Goudreau


1 Answers

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+)

  • avoid mixing CGLIB and JDK proxying as it is not recommended by Spring documentation : Multiple sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the sections (typically from different XML bean definition files) specified. This also applies to the and elements. To be clear: using 'proxy-target-class="true"' on , or elements will force the use of CGLIB proxies for all three of them.

But anyway, my advice is to try to move method security to service layer which normally already supports AOP.

like image 98
Serge Ballesta Avatar answered Feb 15 '23 07:02

Serge Ballesta