`

Hessian源码分析和Hack --让Hessian携带远程调用端的信息(下)

 
阅读更多

接着说Spring包装过的Hessian怎么来Hack。 
刚开始我以为只要改了hessian的源码,就可以了。其实不然,因为Spring通过了几层包装,让你不能得不到request对象。 
Spring里边hessian的入口是HessianServiceExporter这个类,主要方法有两个 

Java代码  收藏代码
  1. public void prepare() {  
  2.     HessianSkeleton skeleton = null;  
  3.   
  4.     try {  
  5.         try {  
  6.             // Try Hessian 3.x (with service interface argument).  
  7.             Constructor ctor = HessianSkeleton.class.getConstructor(new Class[] {Object.class, Class.class});  
  8.             checkService();  
  9.             checkServiceInterface();  
  10.             skeleton = (HessianSkeleton)  
  11.                     ctor.newInstance(new Object[] {getProxyForService(), getServiceInterface()});  
  12.         }  
  13.         catch (NoSuchMethodException ex) {  
  14.             // Fall back to Hessian 2.x (without service interface argument).  
  15.             Constructor ctor = HessianSkeleton.class.getConstructor(new Class[] {Object.class});  
  16.             skeleton = (HessianSkeleton) ctor.newInstance(new Object[] {getProxyForService()});  
  17.         }  
  18.     }  
  19.     catch (Throwable ex) {  
  20.         throw new BeanInitializationException("Hessian skeleton initialization failed", ex);  
  21.     }  
  22.   
  23.     if (hessian2Available) {  
  24.         // Hessian 2 (version 3.0.20+).  
  25.         this.skeletonInvoker = new Hessian2SkeletonInvoker(skeleton, this.serializerFactory);  
  26.     }  
  27.     else {  
  28.         // Hessian 1 (version 3.0.19-).  
  29.         this.skeletonInvoker = new Hessian1SkeletonInvoker(skeleton, this.serializerFactory);  
  30.     }  
  31. }  
  32.   
  33.   
  34. /** 
  35.  * Processes the incoming Hessian request and creates a Hessian response. 
  36.  */  
  37. public void handleRequest(HttpServletRequest request, HttpServletResponse response)  
  38.         throws ServletException, IOException {  
  39.   
  40.     Assert.notNull(this.skeletonInvoker, "HessianServiceExporter has not been initialized");  
  41.             if (!"POST".equals(request.getMethod())) {  
  42.         throw new HttpRequestMethodNotSupportedException(  
  43.                 "POST""HessianServiceExporter only supports POST requests");  
  44.     }  
  45.   
  46.     try {  
  47.       this.skeletonInvoker.invoke(request.getInputStream(), response.getOutputStream());  
  48.     }  
  49.     catch (Throwable ex) {  
  50.       throw new NestedServletException("Hessian skeleton invocation failed", ex);  
  51.     }finally{  
  52.         ServiceContext.end();  
  53.     }  
  54. }  



prepare()方法是在Spring环境加载的时候执行的,用来初始化Hessian的HessianSkeleton并包装成Spring自己的Hessian2SkeletonInvoker。 
handleRequest()方法是每次远程调用的入口,里边的这个方法执行后续hessian的解析流程 

Java代码  收藏代码
  1. this.skeletonInvoker.invoke(request.getInputStream(), response.getOutputStream());  


skeletonInvoker也就是prepare里初始化的Hessian2SkeletonInvoker,跟进去看看先 

Java代码  收藏代码
  1. class Hessian2SkeletonInvoker extends HessianSkeletonInvoker {  
  2.   
  3.     public Hessian2SkeletonInvoker(HessianSkeleton skeleton, SerializerFactory serializerFactory) {  
  4.         super(skeleton, serializerFactory);  
  5.     }  
  6.   
  7.     public void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable {  
  8.         Hessian2Input in = new Hessian2Input(inputStream);  
  9.         if (this.serializerFactory != null) {  
  10.             in.setSerializerFactory(this.serializerFactory);  
  11.         }  
  12.   
  13.         int code = in.read();  
  14.         if (code != 'c') {  
  15.             throw new IOException("expected 'c' in hessian input at " + code);  
  16.         }  
  17.   
  18.         AbstractHessianOutput out = null;  
  19.         int major = in.read();  
  20.         int minor = in.read();  
  21.         if (major >= 2) {  
  22.             out = new Hessian2Output(outputStream);  
  23.         }  
  24.         else {  
  25.             out = new HessianOutput(outputStream);  
  26.         }  
  27.         if (this.serializerFactory != null) {  
  28.             out.setSerializerFactory(this.serializerFactory);  
  29.         }  
  30.   
  31.         this.skeleton.invoke(in, out);  
  32.     }  
  33.   
  34. }  


Hessian2SkeletonInvoker的构造函数进行父类的初始化,也就是初始化了最重要的HessianSkeleton 
再看invoke()方法,是不是有点眼熟,对了,这就是hessian源代码里边的以部分代码,用来包装输入输入流为Hessian自己的Hessian2Input 等,然后判断开头的字节是否正确,以及确定HessianOutput的版本。这些都是解析输入流里边的字节标志位来实现的。 在方法的最后调用了

Java代码  收藏代码
  1. this.skeleton.invoke(in, out);  

,也就是把控制权交给了Hessian来处理,这样后续的工作就是Hessian中完成。但是这样就ok了吗?慢着,我们是不是漏了点什么? 对,那个ServiceContext上下文。因为Hessian是在自己的入口Servlet中生成上下文的,但是Spring并没有生成这个东西。所以,我在这里自己生成了它,唯一一个能够生成的地方就在Spring的HessianServiceExporter的handleRequest()里边,只有在这里才有request对象。因此我把handleRequest()方法中加了一句ServiceContext.begin(request, null, null);然后在finally里边加了一句ServiceContext.end(); 
代码如下: 

Java代码  收藏代码
  1. public void handleRequest(HttpServletRequest request, HttpServletResponse response)  
  2.         throws ServletException, IOException {  
  3.   
  4.     Assert.notNull(this.skeletonInvoker, "HessianServiceExporter has not been initialized");  
  5.     ServiceContext.begin(request, nullnull);  
  6.     if (!"POST".equals(request.getMethod())) {  
  7.         throw new HttpRequestMethodNotSupportedException(  
  8.                 "POST""HessianServiceExporter only supports POST requests");  
  9.     }  
  10.   
  11.     try {  
  12.       this.skeletonInvoker.invoke(request.getInputStream(), response.getOutputStream());  
  13.     }  
  14.     catch (Throwable ex) {  
  15.       throw new NestedServletException("Hessian skeleton invocation failed", ex);  
  16.     }finally{  
  17.         ServiceContext.end();  
  18.     }  
  19. }  



ServiceContext.begin()方法生成一个ThreadLocal对象,ServiceContext.end()则释放它里边的上下文。 
加了这个地方,就可以用上面的hessian源码进行剩余操作了 

分享到:
评论

相关推荐

    hessian-lite-3.2.1-fixed-2.jar

    com.alibaba:hessian-lite:jar:3.2.1-fixed-2 hessian-lite hessian-lite-3.2.1-fixed-2.jar

    Hessian源码分析和Hack.doc

    《Hessian源码分析与Hack:携带远程调用端信息》 Hessian作为一种轻量级的RPC(远程过程调用)框架,因其高效、简洁的二进制协议,被广泛应用于构建Web服务。然而,在实际应用中,有时我们需要获取到远程调用端的IP...

    hessian-4.0.63-API文档-中英对照版.zip

    赠送Maven依赖信息文件:hessian-4.0.63.pom; 包含翻译后的API文档:hessian-4.0.63-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:com.caucho:hessian:4.0.63; 标签:hessian、caucho、jar包、java、...

    java+hessian 远程调用

    - **配置详解**:文档通常会包含如何配置Hessian服务端和客户端的详细步骤,例如设置服务器端的监听端口,客户端的连接参数等。 - **示例代码**:提供服务端和服务端的代码示例,展示如何创建、注册服务以及如何...

    hessian-4.0.63-API文档-中文版.zip

    赠送Maven依赖信息文件:hessian-4.0.63.pom; 包含翻译后的API文档:hessian-4.0.63-javadoc-API文档-中文(简体)版.zip; Maven坐标:com.caucho:hessian:4.0.63; 标签:hessian、caucho、jar包、java、中文文档;...

    Hessian多个版本打包下载

    Hessian是一种高效的二进制序列化协议,常用于远程过程调用(RPC)和服务之间的通信。这个压缩包包含了Hessian的多个版本,分别是Hessian3.1.6、Hessian3.2.1以及Hessian4.0.7。每个版本都有其特定的功能改进和优化...

    hessian-4.0.51-src

    在解压的"**hessian-4.0.51-src**"源码包中,主要包含两个关键文件:"**pom.xml**"和"**src**"。 1. **pom.xml**:这是Maven项目的配置文件,定义了项目依赖、构建过程等信息。通过这个文件,我们可以看到Hessian ...

    hessian-3.3.6-API文档-中英对照版.zip

    赠送jar包:hessian-3.3.6.jar 赠送原API文档:hessian-3.3.6-javadoc.jar 赠送源代码:hessian-3.3.6-sources.jar 包含翻译后的API文档:hessian-3.3.6-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven...

    hessian实现远程调用

    在IT行业中,远程调用是一种常见的技术,使得客户端可以跨网络调用远程服务器上的方法,就像调用本地方法一样方便。Hessian是Apache项目下的一个轻量级的RPC(Remote Procedure Call,远程过程调用)框架,它提供了...

    hessian-3.3.6-API文档-中文版.zip

    赠送Maven依赖信息文件:hessian-3.3.6.pom; 包含翻译后的API文档:hessian-3.3.6-javadoc-API文档-中文(简体)版.zip; Maven坐标:com.alipay.sofa:hessian:3.3.6; 标签:sofa、hessian、alipay、jar包、java、...

    Hessian远程调用框架学习一

    Hessian远程调用框架是基于Java的轻量级RPC(Remote Procedure Call)解决方案,它允许开发者在分布式系统中实现高效、便捷的跨网络对象方法调用。本教程将引导你入门Hessian,通过一个简单的JAVA demo来理解其工作...

    hessian-3.0.20-src.jar

    hessian是一个轻量级的Java Remoting方案

    Hessian-4.0.7(Jar包 + 源码)

    Hessian是一种轻量级的二进制Web服务协议,它由Caucho Technology开发,用于提高远程调用的效率和速度。Hessian 4.0.7是该协议的一个版本,提供了一个Java库,允许开发者在Java应用之间进行高效的数据交换。这个版本...

    hessian-4.0.33.jar

    《深入理解Hessian框架:以hessian-4.0.33.jar为例》 Hessian是一种高效的二进制RPC(Remote Procedure Call)协议,由Caucho Technology开发,旨在提供轻量级、高效的远程调用服务。在这个专题中,我们将以hessian...

    轻量级远程服务调用Hessian的入门实例和与Spring整合的实例.zip

    在服务器端,通过HessianServlet来暴露这个服务,客户端则通过HessianProxyFactory来创建服务代理,从而能够调用远程服务的方法。这种简单设置可以让开发者快速理解Hessian的基本工作原理。 二、Hessian与Spring...

    hessian-lite-3.2.1-fixed-2-sources.jar

    java运行依赖jar包

    spring整合hessian进行远程通讯

    Spring会自动创建代理对象,使得客户端可以通过这个代理对象调用远程服务的方法,就像调用本地对象一样。 3. **使用源码分析**: Hessian库提供了`HessianProxyFactoryBean`和`HessianServiceExporter`这两个关键...

    hessian-lite

    1. **远程调用**:在Dubbo框架中,Hessian-lite用于实现服务调用的二进制序列化和反序列化,使得远程方法调用(RMI)更加高效。它将Java对象转换为二进制流,通过网络发送,然后在服务端反序列化回原来的对象,降低了...

    Hessian Binary Web Service Protocol远程接口调用入门Demo

    Hessian二进制Web服务协议(Hessian Binary Web Service Protocol)是一种高效的、轻量级的远程过程调用(RPC)协议,它主要用于提高Web服务之间的通信效率。Hessian由Caucho Technology公司开发,旨在解决XML-RPC在...

Global site tag (gtag.js) - Google Analytics