Gracias ericacm , pero no funciona por algunas razones:
- Las propiedades de DefaultMethodSecurityExpressionHandler son privadas (la visibilidad de la reflexión es indeseable)
- Al menos en mi Eclipse, no puedo resolver un objeto MethodSecurityEvaluationContext
Las diferencias son que llamamos al método createEvaluationContext existente y luego agregamos nuestro objeto raíz personalizado. Finalmente, acabo de devolver un tipo de objeto StandardEvaluationContext ya que MethodSecurityEvaluationContext no se resolvería en el compilador (ambos son de la misma interfaz). Este es el código que ahora tengo en producción.
Haga que MethodSecurityExpressionHandler use nuestra raíz personalizada:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
// parent constructor
public CustomMethodSecurityExpressionHandler() {
super();
}
/**
* Custom override to use {@link CustomSecurityExpressionRoot}
*
* Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
* configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
*/
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
// due to private methods, call original method, then override it's root with ours
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
return ctx;
}
}
Esto reemplaza la raíz predeterminada al extender SecurityExpressionRoot . Aquí he cambiado el nombre de hasRole a hasEntitlement:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
// parent constructor
public CustomSecurityExpressionRoot(Authentication a) {
super(a);
}
/**
* Pass through to hasRole preserving Entitlement method naming convention
* @param expression
* @return boolean
*/
public boolean hasEntitlement(String expression) {
return hasRole(expression);
}
}
Finalmente, actualice securityContext.xml (y asegúrese de que se haga referencia a él desde su applcationContext.xml):
<!-- setup method level security using annotations -->
<security:global-method-security
jsr250-annotations="disabled"
secured-annotations="disabled"
pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">-->
<bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" />
Nota: la anotación @Secured no aceptará esta anulación ya que se ejecuta a través de un controlador de validación diferente. Entonces, en el xml anterior, los desactivé para evitar confusiones posteriores.