使用@RolesAllowed和@PreAuthorize保护控制器方法

时间:2014-11-18 23:52:51

标签: spring-mvc spring-security

我现在已经把头撞到这个上了一段时间。为了找到合适的解决方案并遵循了大量的Stackoverflow示例和解决方案,我已尽我所能。

首先,我使用基于注释的解决方案。当我注释我的服务时,prePostEnabled可以工作,但是当我注释控制器时,它并没有。此外,即使在我的服务上,jsr250Enabled也无法正常工作。

通过将注释从安全配置移动到MVC配置,我发现很多案例都已关闭,在我的情况下,MVC配置无效。

我的设置如下:https://github.com/spring-projects/spring-security-oauth-javaconfig/tree/master/samples/oauth2-sparklr

但我使用Servlet 3.0并且在我的web.xml中没有任何内容。

My SecurityInitializer如下所示:

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}

我的MVC初始化程序如下所示:

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"};
}

我的WebSecurity配置初始化如下:

@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 {

我的SpringMvcConfig初始化如下:

@Configuration
@EnableWebMvc
@ComponentScan(value = "com.xyz.**.controller")
public class SpringMvcConfig extends WebMvcConfigurerAdapter {

如果您有任何想法,我已经没法了,谢谢!

2 个答案:

答案 0 :(得分:8)

您描述的症状让我想到了代理问题。注释在服务层上运行良好,因为服务通常实现接口,而Spring可以轻松使用JDK代理来放置AOP授权。

但是控制器通常不实现接口。这就是PreAuthorize注释更常用于服务层的原因。恕我直言,您最好尝试使用基于URL模式的授权,而不是在控制器上使用PreAuthorize注释。另一种方法是使用CGLIB的目标类代理。

要使用PreAuthorize和JSR-250注释,您必须

  • 使用以下命令注释Spring安全配置类:

    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
    
  • 如果您在应用程序的其他任何位置使用带有JDK代理的Spring AOP,请在其中使用方法安全实现接口的所有控制器类,声明所有受保护的方法

  • 如果您在应用程序的其他任何地方使用带有CGLIB代理的Spring AOP,请将proxyTargetClass = true添加到@EnableGlobalMethodSecurity

    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true,
            proxyTargetClass = true)
    
  • 如果要在3.2版本的Spring版本下使用CGLIB代理,请将CGLIB库添加到类路径中(CGLIB类包含在Spring 3.2 +中)

  • 避免混合CGLIB和JDK代理,因为Spring文档不推荐:多个部分在运行时折叠成一个统一的自动代理创建者,它应用任何部分的最强代理设置(通常来自指定了不同的XML bean定义文件。这也适用于和元素。 要明确:使用&#39; proxy-target-class =&#34; true&#34;&#39; on,或者元素将强制使用CGLIB代理来处理所有这三个代理。

但无论如何,我的建议是尝试将方法安全性移动到通常已经支持AOP的服务层。

答案 1 :(得分:0)

我注意到的两件事(如this thread所述):

  1. 注释中的prePostEnabled以启用前/后注释
  2. 使用CGLib代理(Serge也提到了这一点)
  3. 您的@EnableGlobalMethodSecurity是否具有这两个属性?

    @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)