Merci ericacm , mais cela ne fonctionne pas pour plusieurs raisons:
- Les propriétés de DefaultMethodSecurityExpressionHandler sont privées (les kludges de visibilité de réflexion ne sont pas souhaitables)
- Au moins dans mon Eclipse, je ne peux pas résoudre un objet MethodSecurityEvaluationContext
Les différences sont que nous appelons la méthode createEvaluationContext existante , puis ajoutons notre objet racine personnalisé. Enfin, je viens de retourner un type d' objet StandardEvaluationContext car MethodSecurityEvaluationContext ne résoudrait pas dans le compilateur (ils proviennent tous deux de la même interface). C'est le code que j'ai actuellement en production.
Faites en sorte que MethodSecurityExpressionHandler utilise notre racine personnalisée:
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;
}
}
Cela remplace la racine par défaut en étendant SecurityExpressionRoot . Ici, j'ai renommé hasRole en 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);
}
}
Enfin, mettez à jour securityContext.xml (et assurez-vous qu'il est référencé à partir de votre 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" />
Remarque: l'annotation @Secured n'acceptera pas ce remplacement car elle s'exécute via un gestionnaire de validation différent. Donc, dans le xml ci-dessus, je les ai désactivés pour éviter toute confusion ultérieure.