Obrigado ericacm , mas não funciona por alguns motivos:
- As propriedades de DefaultMethodSecurityExpressionHandler são privadas (visibilidade do reflexo é indesejável)
- Pelo menos em meu Eclipse, não consigo resolver um objeto MethodSecurityEvaluationContext
As diferenças são que chamamos o método createEvaluationContext existente e, em seguida, adicionamos nosso objeto raiz personalizado. Finalmente, acabei de retornar um tipo de objeto StandardEvaluationContext, já que MethodSecurityEvaluationContext não resolveria no compilador (ambos são da mesma interface). Este é o código que tenho agora em produção.
Faça MethodSecurityExpressionHandler usar nossa raiz 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;
}
}
Isso substitui a raiz padrão estendendo SecurityExpressionRoot . Aqui, renomeei hasRole para 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);
}
}
Por fim, atualize o securityContext.xml (e certifique-se de que seja referenciado no seu 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" />
Observação: a anotação @Secured não aceitará essa substituição, pois ela é executada por um manipulador de validação diferente. Portanto, no xml acima, desativei-os para evitar confusão posterior.