我有一个Web应用程序,配置为以标准方式使用Spring Security 3.2。
我正在使用@PreAuthorize
注释来保护Controllers方法。
现在,我想拒绝访问每个控制器方法 UNLESS 它使用@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>
这种方法也失败了:仍然可以访问未注释的控制器方法。
答案 0 :(得分:1)
我在这里回答我自己的问题。
我使用HandlerInterceptorAdapter解决了这个问题。
我不确定它是实现结果的最常用的方式,但它对我来说已经足够了。
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"/>
答案 1 :(得分:0)
我想出了一种类似的方法,但是它不是对每个请求都执行,而只是扩展了方法的ConfigAttribute
:
一个次要的缺点是它不允许简单的日志记录,或者最大的好处是它遵循与其他不允许的终结点相同的拒绝行为。
SecurityConfig :
@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