Ognl小trick
字数 1285 2025-08-19 12:42:22

OGNL表达式深入解析与实战技巧

1. OGNL概述

1.1 什么是OGNL表达式

OGNL(Object-Graph Navigation Language,对象图导航语言)最初作为WebWork框架的一部分开发,现已成为Apache Struts2的关键组件,并被广泛应用于各种Java框架中。

1.2 对象图导航概念

OGNL的核心在于对象图导航,类似于数据结构中的图:

  • 节点:表示对象
  • :表示对象间的引用关系

示例代码说明:

public class ObjectGraphDemo {
    class People {
        Car car;
    }
    
    class Car {
        String carName = "BMW";
        House house;
    }
    
    class House {
        String houseName = "MyHouse";
    }
    
    public void printPeopleInfo() {
        People people = new People();
        System.out.println(people.car.carName);        // 导航到carName
        System.out.println(people.car.house.houseName); // 导航到houseName
    }
}

2. OGNL核心三要素

OGNL操作必不可少的三个组成部分:

2.1 expression(表达式)

  • OGNL的核心部分
  • 规定解析后需要执行的操作

2.2 root(根对象)

  • 表达式解析后操作的目标对象
  • 可以看作图中的一个节点

2.3 context(上下文)

  • Map类型的数据结构
  • 包含OGNL表达式执行的上下文信息(root也在其中)

3. OGNL基本使用

3.1 基本语法

OGNL语法与Java类似,支持以下操作符:

  • 算术运算符:+, -, *, /, ++, --
  • 比较运算符:==, !=, =
  • 其他运算符:mod, in, not in

3.2 对象访问

  • 非root对象:使用#前缀,如#people1.car.carName
  • root对象:直接访问,如stratt[1]

3.3 静态资源引用

引用类的静态方法和字段:

@class@member 或 @class@method(args)

示例(执行系统命令):

@java.lang.Runtime@getRuntime().exec("calc")

3.4 集合操作

数组操作

public class People {
    public Car car = new Car();
    public String[] stratt = new String[]{"1", "2", "3"};
}

访问方式:

  • root:stratt[1]
  • 非root:#people1.stratt[2]
  • 新建数组:new java.lang.String[]{"a","b","c"}[1]

Map操作

#{"A":"a","B":"b","C":"c"}["B"]

3.5 选择和投影

投影(Projection)

从集合中提取相同属性组成新集合:

group.userList.{username}  // 获取所有user的name列表

选择(Selection)

过滤集合元素:

  • ?:选择满足条件的所有元素
  • ^:选择满足条件的第一个元素
  • $:选择满足条件的最后一个元素

示例:

group.userList.{? #txxx.xxx != null}  // 获取name不为空的user列表

4. 高级技巧:Invocation.class结合OGNL

4.1 技术背景

在MyBatis等框架中频繁使用setAccessible()方法,可以通过Invocation.class绕过反射限制。

4.2 实战应用

  1. 检测类是否存在:
    forName()
    
  2. 构造表达式获取Runtime实例,绕过防护

4.3 测试用例

具体测试用例可参考:OGNL-Test GitHub仓库

5. 安全注意事项

OGNL表达式在Struts2等框架中频繁出现安全漏洞,主要原因包括:

  1. 表达式直接执行系统命令的能力
  2. 反射机制的滥用
  3. 上下文环境的不当配置

开发人员应特别注意对用户输入的OGNL表达式进行严格过滤和验证。

6. 总结

OGNL作为强大的对象图导航语言,提供了:

  • 灵活的对象访问和操作能力
  • 丰富的集合处理功能
  • 静态方法和字段的直接调用
  • 高级选择和投影特性

同时,其强大的功能也带来了安全风险,需要谨慎使用。理解OGNL的核心三要素(expression、root、context)是掌握其用法的关键。

OGNL表达式深入解析与实战技巧 1. OGNL概述 1.1 什么是OGNL表达式 OGNL(Object-Graph Navigation Language,对象图导航语言)最初作为WebWork框架的一部分开发,现已成为Apache Struts2的关键组件,并被广泛应用于各种Java框架中。 1.2 对象图导航概念 OGNL的核心在于对象图导航,类似于数据结构中的图: 节点 :表示对象 边 :表示对象间的引用关系 示例代码说明: 2. OGNL核心三要素 OGNL操作必不可少的三个组成部分: 2.1 expression(表达式) OGNL的核心部分 规定解析后需要执行的操作 2.2 root(根对象) 表达式解析后操作的目标对象 可以看作图中的一个节点 2.3 context(上下文) Map类型的数据结构 包含OGNL表达式执行的上下文信息(root也在其中) 3. OGNL基本使用 3.1 基本语法 OGNL语法与Java类似,支持以下操作符: 算术运算符: +, -, *, /, ++, -- 比较运算符: ==, !=, = 其他运算符: mod, in, not in 3.2 对象访问 非root对象 :使用 # 前缀,如 #people1.car.carName root对象 :直接访问,如 stratt[1] 3.3 静态资源引用 引用类的静态方法和字段: 示例(执行系统命令): 3.4 集合操作 数组操作 访问方式: root: stratt[1] 非root: #people1.stratt[2] 新建数组: new java.lang.String[]{"a","b","c"}[1] Map操作 3.5 选择和投影 投影(Projection) 从集合中提取相同属性组成新集合: 选择(Selection) 过滤集合元素: ? :选择满足条件的所有元素 ^ :选择满足条件的第一个元素 $ :选择满足条件的最后一个元素 示例: 4. 高级技巧:Invocation.class结合OGNL 4.1 技术背景 在MyBatis等框架中频繁使用 setAccessible() 方法,可以通过 Invocation.class 绕过反射限制。 4.2 实战应用 检测类是否存在: 构造表达式获取Runtime实例,绕过防护 4.3 测试用例 具体测试用例可参考: OGNL-Test GitHub仓库 5. 安全注意事项 OGNL表达式在Struts2等框架中频繁出现安全漏洞,主要原因包括: 表达式直接执行系统命令的能力 反射机制的滥用 上下文环境的不当配置 开发人员应特别注意对用户输入的OGNL表达式进行严格过滤和验证。 6. 总结 OGNL作为强大的对象图导航语言,提供了: 灵活的对象访问和操作能力 丰富的集合处理功能 静态方法和字段的直接调用 高级选择和投影特性 同时,其强大的功能也带来了安全风险,需要谨慎使用。理解OGNL的核心三要素(expression、root、context)是掌握其用法的关键。