Apache Commons JEXL的两个版本(3.2.1和3.4.0)之间存在一些不兼容的变化

_mapVars['expr2'].class.name中尝试访问Java对象的class属性,这在3.2.1版本中是允许的,但在3.4.0版本中可能会被视为安全问题而被阻止。有些什么解决方案?

解决方案

  1. 使用自定义函数或封装: 你可以定义一个自定义函数,该函数接受一个对象并返回它的类名。然后,你可以在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
  1. 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();
    
  2. 回退到旧版本: 如果新版本的安全改进对你的应用程序构成了阻碍,并且你无法通过其他方式解决,考虑回退到旧版本。但请注意,这可能会使你的应用面临未解决的安全风险。

建议

建议使用第一个解决方案,因为它提供了更好的控制和灵活性,同时保持了较高的安全性。通过明确地定义哪些功能是允许的,你可以避免未来的安全问题并更好地维护你的代码。

posted @ 2024-10-05 16:55  锐洋智能  阅读(113)  评论(0编辑  收藏  举报