Apache Commons JEXL的两个版本(3.2.1和3.4.0)之间存在一些不兼容的变化
_mapVars['expr2'].class.name中尝试访问Java对象的class属性,这在3.2.1版本中是允许的,但在3.4.0版本中可能会被视为安全问题而被阻止。有些什么解决方案?
解决方案
-
使用自定义函数或封装: 你可以定义一个自定义函数,该函数接受一个对象并返回它的类名。然后,你可以在JEXL表达式中使用这个函数。
定义自定义函数:
java
public class MyJexlFunctions {
public static String getClassName(Object obj) {
return obj.getClass().getName();
}
}
在JEXL引擎中注册并使用该函数:
java
-
JexlEngine jexl = new JexlBuilder().create(); JexlContext context = new MapContext(); JexlScript e = jexl.createScript("_mapVars['expr2']|getClassName"); // 将自定义函数加入到引擎中 Map<String, Object> funcs = new HashMap<>(); funcs.put("getClassName", new MyJexlFunctions()); JexlContext jc = new MapContext(funcs); String className = (String) e.execute(jc);
-
修改JEXL的安全策略: 如果你有能力控制JEXL引擎的安全策略,并确信访问class属性是安全的,你可以修改或扩展JEXL的安全性策略,以允许访问某些属性。
java
-
JexlEngine jexl = new JexlBuilder().create(); JexlSandbox sandbox = new JexlSandbox(true); // true for white-listing, false for black-listing sandbox.white("java.lang.Class", "name"); // Allow access to `name` property of Class JexlBuilder builder = new JexlBuilder().sandbox(sandbox); JexlEngine jexl = builder.create();
-
回退到旧版本: 如果新版本的安全改进对你的应用程序构成了阻碍,并且你无法通过其他方式解决,考虑回退到旧版本。但请注意,这可能会使你的应用面临未解决的安全风险。
建议
建议使用第一个解决方案,因为它提供了更好的控制和灵活性,同时保持了较高的安全性。通过明确地定义哪些功能是允许的,你可以避免未来的安全问题并更好地维护你的代码。