感谢ericacm,但由于以下几个原因它不起作用:
-
DefaultMethodSecurityExpressionHandler 的属性是私有的(反射可见性不受欢迎)
- 至少在我的 Eclipse 中,我无法解析 MethodSecurityEvaluationContext 对象
不同之处在于我们调用现有的createEvaluationContext 方法,然后添加我们的自定义根对象。最后我只返回了一个 StandardEvaluationContext 对象类型,因为 MethodSecurityEvaluationContext 不会在编译器中解析(它们都来自同一个接口)。这是我现在在生产中的代码。
让 MethodSecurityExpressionHandler 使用我们的自定义根:
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;
}
}
这将通过扩展 SecurityExpressionRoot 替换默认根。这里我将 hasRole 重命名为 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);
}
}
最后更新 securityContext.xml(并确保它是从您的 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" />
注意:@Secured 注释将不接受此覆盖,因为它通过不同的验证处理程序运行。因此,在上面的 xml 中,我禁用了它们以防止以后混淆。