Ok Encontré una manera de evitar AccessDeniedException. Sin embargo, esto no resuelve el problema. La ejecución del resto del código ahora se cumple normalmente, sin embargo, la llamada al método seguro no se previene incluso cuando hasPermission devuelve false.
Así es como me las arreglé para evitar que el AccessDeniedException de parando todo:
Es necesario implementar un AccessDecisionManager donde se impide la AccessDeniedException propagación. Esa es la parte fácil. El mío se ve así:
public class SkipMethodCallAccessDecisionManager extends AffirmativeBased {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes){
try{
super.decide(authentication, object, configAttributes);
}catch(AccessDeniedException adex){
logger.debug("Access Denied on:" + object);
}
}
}
Luego, la parte difícil ... configurar el contexto de la aplicación.
<sec:global-method-security pre-post-annotations="enabled" access-decision-manager-ref="skipMethodCallAccessDecisionManager "/>
<bean id="skipMethodCallAccessDecisionManager" class="com.application.auth.vote.SkipMethodCallAccessDecisionManager ">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter">
<constructor-arg ref="expressionBasedPreInvocationAdvice"/>
</bean>
<!-- Insert RoleVoter if required -->
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</list>
</property>
</bean>
<bean id="expressionBasedPreInvocationAdvice" class="org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice">
<property name="expressionHandler" ref="expressionHandler"/>
</bean>
¿Alguna idea sobre cómo evitar que se llame al método sin detener todo?
Terminé haciendo algo bastante más simple, acabo de agregar un consejo sobre el MethodSecurityInterceptor que capta la excepción con un @Around para que la propagación más allá de ese punto se evite . De esa manera podría evitar configurar Spring Security a pie, lo cual es muy intrincado. Sin embargo, lo que propones es la forma canónica de hacerlo y funciona. – Chepech
¡Muy bonito! Me pregunto si hay alguna manera de que podamos cambiar el comportamiento de beforeInvocation() (usando AOP) para verificar los permisos del usuario en un método específico (que OP quiere proteger) y reemplazar mi por una instancia ficticia de MethodInvocation en lugar de preocuparme por AccessDeniedException. – Ritesh
@Chepech La solución @Around parece muy simple y elegante. Si actualiza el código @Around en cuestión, con mucho gusto lo votaré. – Ritesh