java Ogal
先粗略的学一下后面再来
Ognl
OGNL (Object Graph Navigation Language) 是一个开源的表达式引擎。通过使用OGNL,我们能够通过表达式存取Java对象树中的任意属性和调用Java对象树的方法等。也就是说,如果我们把表达式看成是一个带有语义的字符串,那么OGNL就是这个语义字符串与Java对象之间沟通的催化剂,通过OGNL,我们可以轻松解决在数据流转的过程中所碰到的各种问题。
对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个 “路径” 来完成对象信息的导航,这个 “路径” 可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成。
OGNL语法
.
操作符:如上所示,可以调用对象的属性和方法,hacker.name
,且上一个节点的结果作为下一个节点的上下文,如(#a=new java.lang.String("calc")).(@java.lang.Runtime@getRuntime().exec(#a))
,也可以换成逗号(#a=new java.lang.String("calc")),(@java.lang.Runtime@getRuntime().exec(#a))
@
操作符:用于调用静态对象、静态方法、静态变量,@java.lang.Math@abs(-10)
#
操作符:a)用于调用非root对象
1
2
3
4
5
6
7// 放入Context中,但不是root
context.put("user", user)
// 创建Expression,非root,所以要加上#
String expression = "#user.name";
Object ognl = Ognl.parseExpression(expression);
// 调用
Object value = Ognl.getValue(ognl,context,context.getRoot());b)创建Map
1
#{"name": "chenlvtang", "level": "noob"}
c)定义变量
1
#a=new java.lang.String[]{"calc"}
$
操作符:一般用于配置文件,<param name="name">${name}</param>
%
操作符:计算其中的OGNL表达式,%{hacker.name}
List:直接使用
{"green", "red", "blue"}
创建对象创建:
new java.lang.String[]{"foobar"}
三要素
表达式(Expression):
表达式是整个 OGNL 的核心内容,所有的 OGNL 操作都是针对表达式解析后进行的。通过表达式来告诉 OGNL 操作到底要干些什么。因此,表达式其实是一个带有语法含义的字符串,整个字符串将规定操作的类型和内容。OGNL 表达式支持大量的表达式,如 “链式访问对象”、表达式计算、甚至还支持 Lambda 表达式。
Root 对象:
OGNL 的 Root 对象可以理解为 OGNL 的操作对象。当我们指定了一个表达式的时候,我们需要指定这个表达式针对的是哪个具体的对象。而这个具体的对象就是 Root 对象,这就意味着,如果有一个 OGNL 表达式,那么我们需要针对 Root 对象来进行 OGNL 表达式的计算并且返回结果。
上下文环境:
有个 Root 对象和表达式,我们就可以使用 OGNL 进行简单的操作了,如对 Root 对象的赋值与取值操作。但是,实际上在 OGNL 的内部,所有的操作都会在一个特定的数据环境中运行。这个数据环境就是上下文环境(Context)。OGNL 的上下文环境是一个 Map 结构,称之为 OgnlContext。Root 对象也会被添加到上下文环境当中去。
说白了上下文就是一个 MAP 结构,它实现了 java.utils.Map 的接口。
使用Ognl
1 | <dependency> |
示例代码:
示例类:sample.ognl.Address
1 |
|
OgnlContext对象
OgnlContext对象是ognl表达式语言的核心。
但是项目中不会要求写OgnlContext的代码,Ognl标签其实是调用了OgnlContext对象。所以只做了解即可。
OgnlContext对象在源码中实现了Map接口:public class OgnlContext implements Map {……}
Ognl表达式语言取值,也是用java代码取值的,原理就是使用OgnlContext和Ognl这两个类,只需要记住,Ognl取根元素不用#号,取非根元素要使用#号:
OgnlContext类
硬编码方式,了解OgnlContext对象,因为OgnlContext对象实现是Map接口,所有OgnlContext本质就是一个Map,可以使用map方法:
OgnlContext context = new OgnlContext();
context.put(“uesr”,user);
context.put(“address”,address);
context.setRoot(address);
Ognl类
Ognl类也是Ognl底层运行的代码,常用的api如下:
Object obj1 = Ognl.parseExpression(“country”); 解析ognl表达式
Ognl.getValue(obj1, context, context.getRoot()); 获取ognl的表达式值,obj1是上面一个api,其他两个分别是创建的上下文对象以及一个不用修改的参数
Object obj2 = Ognl.parseExpression(“language.toUpperCase()”); 方法调用
Object obj3 = Ognl.parseExpression(“@java.lang.Integer@toBinaryString(10)”);等同于上面
Object obj4 = Ognl.parseExpression(“@@min(10,4)”); Math类的方法直接调用,静态方法的调用
代码示例如下:
1 | package o_ognl; |
ValueStack对象
等以后学struts再来学
https://www.cnblogs.com/cenyu/p/6233942.html
表达式注入
1 | public class MyOGNL { |
运行后,成功弹出计算器。
OGNL 高版本下的黑名单
OGNL在>=3.1.25、>=3.2.12的版本中增加了黑名单。我们将依赖更新为3.1.25,然后再次运行,就会得到一个报错信息
发现禁用了这些能命令执行的函数或者类
https://chenlvtang.top/2022/08/11/Java%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B3%A8%E5%85%A5%E4%B9%8BOGNL/