如何在java中解组ruby对象?

时间:2009-11-18 21:55:24

标签: java ruby jruby marshalling

我有一个对象,我想抓住java中的内容。 唯一的问题是目前是红宝石。

irb(main):050:0> blah
=> "BAh7ByIeYXV0aGVudGljYXRpb25fc3RyYXRlZ2llczAiCXVzZXJpBg%253D%253D-\
-0cdecf4edfaa5cbe4693c9fb83b204c1256a54a6"

irb(main):049:0> Marshal.load(Base64.decode64(blah))
=> {"authentication_strategies"=>nil, "user"=>1}

我得到了base64部分 - 所以现在一切都以字节为单位。我如何访问第二个字符串?我认为可以用jruby完成一些事情,但我以前从未使用它,也不知道从哪里开始。

让我在这里详细说明我的问题。

1)这些是我试图在tomcat上的servlet和apache上的merb应用程序之间共享的cookie

2)我不打算将它们存储在数据库中。我曾考虑过在memcached中使用它们,但出于其他原因我想将它们存储为cookie(是的,我很清楚所涉及的安全隐患)

我目前正在查看jruby的Red Bridge / jruby-embed,但是因为这只是70字节我需要看一下,我觉得把所有开销都搞得那么简单就太荒谬了。

而不是启动一个新问题....我现在的代码看起来像是这样:

        // using commons
        Base64 b64 = new Base64();
        byte[] decoded = b64.decode(cookie.getValue().getBytes());

        ScriptingContainer container = new ScriptingContainer();
        container.runScriptlet("la = Marshal.load(\"" + decoded + "\"); puts la.to_s;");

显然这不会起作用因为元帅会检查解码的前2个字节并且因为它与jruby的主要/次要版本不匹配而疯狂...... hrmss ..

3 个答案:

答案 0 :(得分:3)

对于不涉及JRuby的解决方案,为什么不自行序列化您感兴趣的字段?例如,将它们作为原始字符串保存到文件或关系数据库中?

我意识到这可能不会完全回答这个问题但是你可能以前没有想过这个问题!

编辑 - feydr 已明确表示他并未谈论将对象数据序列化到文件中。因此,我认为序列化是用于进程间通信,在这种情况下,通过套接字提供的二进制协议(或任何协议)是一个很好的解决方案并且易于实现。你可能会比查看Google protocol buffers更糟糕(它甚至可以在Java端进行代码生成)。

答案 1 :(得分:2)

确定!这就是我做的。让我重新思考一下我的目的是从merb到一个在tomcat下运行的servlet的cookie会话。

import java.io.*;
import java.util.*;
import org.jruby.embed.ScriptingContainer;
import org.apache.commons.codec.binary.Base64;
import javax.servlet.*;
import javax.servlet.http.*;

public class process extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   HttpSession session = request.getSession(true);

    PrintWriter out = response.getWriter();
    Cookie[] cookies = request.getCookies();

    for(int i=0; i<cookies.length; i++) {
      Cookie cookie = cookies[i];

      // base64 decode, then un-marshall ruby style...
      // finally figure out what to do with our session secret key
      if(cookie.getName().equals("_session_id")) {
        ScriptingContainer container = new ScriptingContainer();
        container.setWriter(out);
        container.runScriptlet("require 'base64'; puts \"" + cookie.getValue() + "\"; " +
                              "puts Marshal.load(Base64.decode64(\"" + cookie.getValue() + "\")).to_s; ");
      }                       

    } 

}     
}

显然这段代码可以清理很多 - 例如:将base64解码移回java - 但是这将从merb获得一个cookie。现在我只需要在那里抛出验证器以确保它不是伪造的。

感谢大家的建议!

答案 2 :(得分:1)

您也可以考虑使用适用于RubyJava(以及C ++和Python)的Google协议缓冲区。