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

Chr*_*eau 3 spring-mvc spring-security

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

首先,我使用基于注释的解决方案.当我对我的服务进行注释时,prePostEnabled可以工作,但是当我注释控制器时却没有.此外,即使在我的服务上,jsr250Enabled也不起作用.

通过将注释从安全配置移动到MVC配置,我发现很多情况已经关闭,在我的情况下这不起作用.

我有一个看起来像这样的设置:https://github.com/spring-projects/spring-security-oauth-javaconfig/tree/master/samples/oauth2-sparklr

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

我的SecurityInitializer看起来像这样:

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
Run Code Online (Sandbox Code Playgroud)

我的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"};
}
Run Code Online (Sandbox Code Playgroud)

我的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 {
Run Code Online (Sandbox Code Playgroud)

我的SpringMvcConfig初始化如下:

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

如果你有任何想法,我就没有果汁了,谢谢!

Ser*_*sta 8

您描述的症状让我想到了代理问题.注释在服务层上工作正常,因为服务通常实现接口,而Spring可以轻松地使用JDK代理来实现AOP授权.

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

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

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

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

  • 如果你使用你的应用程序中的其他任何地方Spring AOP与CGLIB代理,添加proxyTargetClass = true@EnableGlobalMethodSecurity:

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

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

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