Spring Security:如果缺少 @PreAuthorize 注释,则拒绝访问控制器方法
Posted
技术标签:
【中文标题】Spring Security:如果缺少 @PreAuthorize 注释,则拒绝访问控制器方法【英文标题】:Spring Security: Deny access to controller methods, if @PreAuthorize annotation is missing 【发布时间】:2015-08-01 15:38:07 【问题描述】:我有一个配置为以标准方式使用 Spring Security 3.2 的 Web 应用程序。
我正在使用@PreAuthorize
注释来保护Controllers 方法。
现在,我想拒绝访问每个控制器方法除非用@PreAuthorize
注释。
我尝试了以下方法:
超级控制器
每个控制器都从带有注释的超级控制器扩展而来:@PreAutorize("denyAll")
。这种方法似乎不起作用,因为控制器的方法注释被忽略了。一切都是禁止的。
@PreAutorize("denyAll")
public class SuperController
public class MyController extends SuperController
@PreAuthorize("hasRole('SUPERHERO')")
@RequestMapping(value = URL_PREFIX + "Add.do", method = RequestMethod.GET)
public String doStuff(Model model)
...
aop
在全局方法安全标签中使用切入点表达式
<global-method-security pre-post-annotations="enabled">
<protect-pointcut expression="execution(* com.acme.*Controller.*(..))" access="denyAll" />
</global-method-security>
这种方法也失败了:没有注释的控制器方法仍然可以访问。
【问题讨论】:
【参考方案1】:我在这里回答我自己的问题。
我已经使用HandlerInterceptorAdapter 解决了这个问题。
我不确定这是实现结果的最符合 Spring 的惯用方式,但对我来说已经足够了。
public class MvcPreAuthorizeAnnotationCheckerInterceptor extends HandlerInterceptorAdapter
final HandlerMethod hm;
if (handler instanceof HandlerMethod)
hm = (HandlerMethod) handler;
PreAuthorize annotation = hm.getMethodAnnotation(PreAuthorize.class);
if (annotation == null)
// check if the class is annotated...
annotation = hm.getMethod().getDeclaringClass().getAnnotation(PreAuthorize.class);
if (annotation == null)
// add logging
// or send a NON AUTHORIZED
response.sendRedirect(request.getContextPath());
return true;
在 Spring 配置中:
<mvc:interceptors>
<beans:ref bean="mvcPreAuthorizeAnnotationCheckerInterceptor"/>
</mvc:interceptors>
<beans:bean id="mvcPreAuthorizeAnnotationCheckerInterceptor" class="com.acme.MvcPreAuthorizeAnnotationCheckerInterceptor"/>
【讨论】:
【参考方案2】:我想出了一个类似的方法,但它不是对每个请求都执行,只是扩展了该方法的ConfigAttribute
:
一个小缺点可能是它不允许简单的日志记录,或者最大的好处是它遵循与其他不允许的端点相同的拒绝行为。
安全配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource()
return new CustomPermissionAllowedMethodSecurityMetadataSource();
元数据源:
public class CustomPermissionAllowedMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource
@Override
protected Collection<ConfigAttribute> findAttributes(Class<?> clazz)
return null;
@Override
protected Collection<ConfigAttribute> findAttributes(Method method, Class<?> targetClass)
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
List<ConfigAttribute> attributes = new ArrayList<>();
// if the class itself is annotated as a @Controller we should by default deny access to every method
if (AnnotationUtils.findAnnotation(targetClass, Controller.class) != null)
attributes.add(DENY_ALL_ATTRIBUTE);
if (annotations != null)
for (Annotation a : annotations)
// but not if the method has at least a PreAuthorize or PostAuthorize annotation
if (a instanceof PreAuthorize || a instanceof PostAuthorize)
return null;
return attributes;
@Override
public Collection<ConfigAttribute> getAllConfigAttributes()
return null;
我还写了一篇关于这个的小文章,还有一些背景:https://www.baeldung.com/spring-deny-access
【讨论】:
以上是关于Spring Security:如果缺少 @PreAuthorize 注释,则拒绝访问控制器方法的主要内容,如果未能解决你的问题,请参考以下文章
在 Grails 中使用 Pre/Post Spring-Security Annotations
如何将 Spring Security @Pre 和 @Post 注释与集合一起使用
如何让 Spring Security 使用 OAUTH2 响应 Pre-Flight CORS 请求