Spring Security:如果缺少@PreAuthorize注释,则拒绝访问控制器方法

时间:2015-05-20 11:50:13

标签: java spring spring-security

我有一个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>

这种方法也失败了:仍然可以访问未注释的控制器方法。

2 个答案:

答案 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