使用@RolesAllowed和@PreAuthorize保护控制器方法
问题内容:
我已经把头撞了一段时间了。为了找到合适的解决方案,我已竭尽所能,并遵循了许多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 {
}
我的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 {
如果您有任何想法,我就没钱了,谢谢!
问题答案:
您描述的症状使我想到了代理问题。注释在服务层上运行良好,因为服务通常实现接口,并且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库添加到类路径(Spring 3.2+中包含CGLIB类)
-
避免混合使用CGLIB和JDK代理,因为Spring文档不建议这样做: 在运行时将多个部分折叠到一个统一的自动代理创建器中,该创建器将应用任何部分中最强的代理设置(通常来自不同的XML bean定义文件)指定。 这也适用于和元素。 需要明确的是:在或元素上使用’proxy-target-class =“ true”’会强制对所有三个元素使用CGLIB代理。
但是无论如何,我的建议是尝试将方法安全性转移到通常已经支持AOP的服务层。