Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

spring mvc - 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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...