感谢ericacm,但由于以下原因它无法正常工作:
- DefaultMethodSecurityExpressionHandler的属性是私有的(反射可见性不受欢迎)
- 至少在我的Eclipse中,我无法解析MethodSecurityEvaluationContext对象
区别在于我们调用现有的createEvaluationContext方法,然后添加我们自定义的根对象。最后,我只返回了一个StandardEvaluationContext对象类型,因为MethodSecurityEvaluationContext在编译器中不能解析(它们都来自同一个接口)。这是我现在在生产中使用的代码。
使MethodSecurityExpressionHandler使用我们的自定义根对象:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
public CustomMethodSecurityExpressionHandler() {
super();
}
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
return ctx;
}
}
通过扩展 SecurityExpressionRoot 来替换默认的根。在这里我将 hasRole 重命名为 hasEntitlement:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
public CustomSecurityExpressionRoot(Authentication a) {
super(a);
}
public boolean hasEntitlement(String expression) {
return hasRole(expression);
}
}
最后更新securityContext.xml文件(确保它在applcationContext.xml文件中被引用):
<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="com.yourSite.security.CustomMethodSecurityExpressionHandler" />
注意: @Secured注解不会接受此覆盖,因为它通过不同的验证处理程序运行。因此,在上面的xml中,我禁用了它们以防止后续混淆。