文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java安全基础之Java的反射机制

2024-12-01 13:01

关注

一、什么是反射

反射(Reflection)是Java的特征之一,C/C++语言中不存在反射,反射的存在使得运行中的Java程序能够获取自身的信息,并且可以操作类或对象的内部属性。那什么是反射呢?

下面是官方的解释:

反射使得Java代码能够发现有已加载类的字段、方法和构造函数的信息,并在安全限制内使用反射的字段、方法和构造函数对其底层对应的对象进行操作

简单来说,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。同样的,Java的反射机制也是也是如此,在运行状态中,通过Java的反射机制,我们能够判断一个对象所属的类;了解任意一个类的所有属性和方法;能够调用任意一个对象的任意方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

二、反射的用途

在静态语言中,一般对象的类型都是在编译期就确定下来的,二通过Java反射机制,可以动态的创建对象并调用其方法或属性,这也就使得的反射的用途很广泛,在开发过程中使用Eclipse、IDEA等开发工具时,当我们输入一个对象或类并想调用它的属性或方法时,编译器会自动列出它的属性或方法,这是通过反射实现的;载入,JavaBean和jsp之间的调用也是通过反射实现的。反射最重要的用途是开发各种框架,如上文中提到的Spring框架以及ORM框架,都是通过反射机制来实现的。

面向不同的用户,反射机制的重要程度也大不相同。对于框架开发人员来说,反射虽小但作用非常大,它是各种容器实现的核心。对于一般的开发者来说,反射的作用相对较小。但总体来说,适当了解二框架的底层机制对我们的编程思想也是非常有帮助的。

三、静态语言和动态语言

在学习反射之前,我们有必要了解一下什么是动态语言和静态语言

静态语言是在编译时变量的数据类型即可确定的语言,多数静态语言要求在使用变量之前必须声明数据的类型。如C++、Java、Delphi、C#等

动态语言时在运行是确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。如PHP/ASP/Ruby/Python.Perl/ABAP/SQL/JavaScript/Unix Shell等等。

可以在程序运行时改变程序结构和变量类型的语言,比如在程序运行时,新的类和对象可以被加载和创建,新的函数或方法可以被加入或者去除等等。

3.1、动态特性

动态语言具有的某些特性即为动态特性

以PHP举例,一段代码,其中变量值的改变可鞥导致这段代码发生功能上的变化,我们将这种现象称为PHP的动态特性

比如下面的这个例子

我们只有当代码运行时,通过变量传入的值才能确定其具体功能

3.2、动态特性与Java反射

正是因为PHP中存在多种动态特性,使得开发人员能通过很少的代码实现非常多的功能,比较经典的例子就是一句话木马,通过一行

但是Java本身是一门静态语言,无法像PHP那么灵活多变。但是通过Java反射机制,可以为自身提供一些动态特性。比如,当我们通过IDE写代码时,敲击点好号“.”,会出现当前对象或类所包含的属性和方法,这里用到的就是Java反射机制。

反射最重要的用途就是开发各种通用框架,很多框架嗾使通过XML文件来进行配置的(如:struts.xml,spring-*.xml等),即所谓的框架核心配置文件。为了确保框架的通用性,程序运行时需要根据配置文件中对应的内容加载不同的类或对象,调用不同的方法,这也依赖于Java反射机制。

3.3、Java反射机制功能点

综上所述,Java反射机制的功能可分为如下几点:

四、Java的命令执行类

4.1、java.lang.Runtime类

这个类是一个共有类,每个Java应用程序都有一个Runtime类实例,它允许应用程序与运行应用程序的环境交互。当前运行时可以从getRuntime方法获得。应用程序无法创建自己的此类实例。

该类的主要方法是:getRuntime(),得到一个和当前程序相关联的Runtime类的对象,解释如下:

返回与当前Java应用关联的runtime对象。大多数Runtime类的方法是实例方法,所以必须被当前运行时对象调用。

Runtime对象可以调用exec()方法执行命令,详细文档解释如下:

在一个单独的进程中执行指定的命令。这是一个方便的方法。以exec(command)形式调用与exec(String,Stringp[],file)的表现是相同的。

下面是一段代码示例:

五、获取类对象

获取类对象的方式有很多种,这里提供四种方式

5.1、获取类对象-forName()

如果要使用Class类中的方法完成,就需要使用forName方法,只要有类名称即可,更为防爆,扩展性更强。这种方法并不陌生,在配置JDBC的时候,我们通常采用这种方法

5.2、获取类对象-直接获取

任何数据类型都具备一个静态的属性,可以使用.class来获取其对应的Class对象。这种方法相对简单,但还是要明确用到类的静态成员

5.3、获取类对象-getClass()

我们可以通过Object类中的getClass()方法来获取字节码对象,不过这种方式较为繁琐,必须要明确具体的类,然后创建对象

六、获取类方法

获取某个Class对象的方法集合,主要有以下几种方法:

6.1、获取类方法-getDeclaredMethods

getDeclaredMethods方法返回类或接口声明的所有方法,包括:public、protected、private和默认方法,但不包括继承的方法

6.2、获取类方法-getMethods

getMethods方法返回某个类的所有public方法,包括其继承的public方法

6.3、获取类方法-getMethod

getMethod方法只能返回一个特定的方法,如 Runtime类中的exec()方法,该方法的第一个参数为方法名称,后面的参数为方法的参数对应Class的对象

6.4、获取类方法 - getDeclaredMethod

getDeclaredMethod方法与getMethod类似,也只能返回一个特定的方法,该方法的第一个参数为方法名,第二个参数名是方法参数

七、获取类成员变量

为了更直观地体现出获取类成员变量的方法,我们首先创建一个Student类,要获取Student类成员变量,主要有以下几个方法:

7.1、获取类成员变量-getDeclaredFields

getDeclaredFields方法能够获得类成员变量数组,包括public、private和proteced,但是不包括父类的声明字段

7.2、获取类成员变量-getFields

gteFields能够获得某个类的所有的public字段,包括父类中的字段

7.3、获取类成员变量-getDeclaredField

该方法与getDeclaresFields的区别是只能获得类的单个成员变量

7.4、获取类成员变量-getField

与getFields类似,getField方法能够获得某个类特定的public字段,包括父类中的字段

八、构造任意类的对象

构造任意类的对象最经典的方式:

无参数:className.newInstance()

有参数:getConstructor().newInstance()

构造任意类的对象两种方式异同

(1)首先两种方式在原始码所在的位置上不同

(2)在使用方法上的不同

- Class.forName("com.ms08067.newInstance.newInstanceExample").newInstance();

- newInstanceExample.class.newInstance();
- newInstanceExample.class.getConstructor().newInstance();

九、调用任意实例对象的方法

调用任意实例对象的方法最经典的方式

invoke方法调用任意实例对象是通过反射实现的,下面是一个示例:

十、不安全的反射

如前所述,利用Java的反射机制,我们可以无视类方法、变量访问权限修饰符,调用任何类的任意方法、访问并修改成员变量值,但是这样做可能导致安全问题,如果一个攻击者能够通过应用程序创建意外的控制流路径,就有可能绕过安全检查发起相关攻击。假设有一段代码如下:

其中存在一个字段name,当获取用户请求的name字段后进行判断,如果请求的是Delect操作,则执行DelectCommand函数;若执行的是Add操作,则执行AddCommand函数;如果不是这两种操作,则执行其他代码。

假如开发者看到了这段代码,他认为可以使用Java的反射来重构此代码以减少代码行,如下所示:

这样的重构看起来使得代码行减少,消除了if/else块,而且可以在不修改命令分派器的情况下添加新的命令类型,但是如果没有对传入的name字段进行限制,则可以实例化实现Command接口的任何对象,从而导致安全问题。实际上,攻击者甚至不局限于本例中的Command接对象,而是使用任何其他对象来实现,如调用系统中任何对象的默认构造函数,或者调用Runtime对象去执行系统命令,这可能导致远程命令执行漏洞,因此不安全的反射的危害性极大,也是我们审计过程中需要重点关注的内容。

来源:FreeBuf.COM内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯