(对不起,如果这是重复的,但这个问题对搜索引擎非常不友好。)
我想知道如何在 EL 中评估 Spring EL(所有函数、变量、上下文等都通过)。
具体来说,我想动态评估从@PreAuthorize
.
即类似的东西@PreAuthorize("eval(argument.securityExpr)")
。
您可以扩展 Springs MethodSecurityExpressionRoot(并在您自己的 MethodSecurityExpressionHandler 中创建它)并添加一个除字符串之外的 eval 方法,并让 SpringExpressionParser 评估字符串。应该管用...
编辑:
一小段代码:
public class MySpringSecurityRoot extends MethodSecurityExpressionRoot {
private MyMethodSecurityExpressionHandler handler; // to be injected in the handler
public boolean eval(String expression) {
Expression expression = handler.getExpressionParser().parseExpression(expression);
return ExpressionUtils.evaluateAsBoolean(
handler.getExpressionParser().parseExpression(expression),
handler.createEvaluationContext(authentification, methodInvocation));
}
}
您的处理程序必须设置为默认方法安全表达式处理程序:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="myHandler"/>
</security:global-method-security>
现在您的 eval 函数可以在每个方法安全表达式中访问
但是:您必须意识到描述您的安全规则的人可以访问当前 spring 上下文中的所有 bean!可能是安全漏洞。
如果您使用 simpleparametername discover with@
来评估权限,您几乎可以做任何您想做的事情,而无需启用调试模式。
@PreAuthorize("@mySecurityService.hasPermission(#arg0)")
public String getSpecial(final String special) {
return "authorized";
}
mySecurityService 可以是返回布尔值的任何 bean/方法,并将其连接到 arg1
public class SimpleParameterNameDiscoverer implements ParameterNameDiscoverer {
public String[] getParameterNames(Method m) {
return getParameterNames(m.getParameterTypes().length);
}
public String[] getParameterNames(Constructor c) {
return getParameterNames(c.getParameterTypes().length);
}
protected String[] getParameterNames(int length) {
String[] names = new String[length];
for (int i = 0; i < length; i++)
names[i] = "arg" + i;
return names;
}
}
和上下文:
<bean id="methodSecurityExpressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="parameterNameDiscoverer">
<bean class="your.path.SimpleParameterNameDiscoverer"/>
</property>