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 sont indésirables)
- Au moins dans mon Eclipse, je ne peux pas résoudre un MethodSecurityEvaluationContext objet
Les différences sont que nous appelons l'existant createEvaluationContext et ensuite ajouter notre objet Root personnalisé. Enfin, je viens de renvoyer un Contexte d'évaluation standard puisque MethodSecurityEvaluationContext ne serait pas résolu dans le compilateur (ils sont tous deux issus de la même interface). Voici le code que j'ai maintenant en production.
Faire MethodSecurityExpressionHandler utiliser 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" />
Nota: l'annotation @Secured n'acceptera pas ce remplacement car elle passe par un gestionnaire de validation différent. Donc, dans le xml ci-dessus, je les ai désactivés pour éviter toute confusion ultérieure.
2 votes
Je n'ai pas le temps de taper une réponse pour le moment, mais j'ai suivi ce guide et cela a fonctionné à merveille : baeldung.com/ J'utilise Spring Security 5.1.1.