如何以编程方式解析hasRole('admin')
之类的spring(web)安全表达式(不使用标记,注释或...
)? (reference doc)
我找到Spring: What parser to use to parse security expressions - 但我不知道如何查找或构建EvaluationContext
例如在弹簧控制器内部。
不提供EvaluationContext
给予
org.springframework.expression.spel.SpelEvaluationException: EL1011E:(pos 0): Method call: Attempted to call method hasRole(java.lang.String) on null context object
答案 0 :(得分:2)
你需要添加几个东西才能让这个东西运转起来。你必须插入Spring的安全API。这是我如何做到的,它在Spring 3.2中运行良好。 首先,如前所述,您必须在spring-context.xml中具有类似的配置:
<security:http access-decision-manager-ref="customAccessDecisionManagerBean">
<security:http/>
<bean id="customWebSecurityExpressionHandler"
class="com.boyan.security.CustomWebSecurityExpressionHandler"/>
<bean id="customAccessDecisionManagerBean"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
<property name="expressionHandler" ref="customWebSecurityExpressionHandler" />
</bean>
</list>
</property>
</bean>
这定义了一个新的expressionHandler来覆盖WebExpressionVoter的默认值。然后我们将这个新决策选民添加到决策经理。 CustomWebSecurityExpressionHandler用于控制SecurityExpressionRoot的创建。到现在为止还挺好。问题是为什么你需要一个CustomWebSecurityExpressionRoot,答案很简单 - 你在那里定义自定义安全方法。考虑到这一点,我们可以编写以下类:
public class CustomWebSecurityExpressionHandler extends DefaultWebSecurityExpressionHandler {
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, FilterInvocation fi) {
CustomWebSecurityExpressionRoot expressionRoot =
new CustomWebSecurityExpressionRoot(authentication, delegationEvaluator);
return expressionRoot;
}
}
}
public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot {
public CustomWebSecurityExpressionRoot(Authentication auth, FilterInvocation fi) {
super(auth, fi);
}
// in here you must define all of the methods you are going to invoke in @PreAuthorize
// for example if you have an expression with @PreAuthorize('isBoyan(John)')
// then you must have the following method defined here:
public boolean isBoyan(String value) {
//your logic goes in here
return "Boyan".equalsIgnoreCase(value);
}
}
如果要获取ExpressionParser的引用,可以使用以下方法AbstractSecurityExpressionHandler.getExpressionParser()。它可以通过CustomWebSecurityExpressionHandler访问。如果你想做一些更具体的事情,你也可以看看它的API。 我希望这能回答你的问题。