在play framework 2.4中,如何访问ssl socket(或ssl client cert)

Posted

技术标签:

【中文标题】在play framework 2.4中,如何访问ssl socket(或ssl client cert)【英文标题】:In play framework 2.4, how to access ssl socket (or ssl client cert) 【发布时间】:2015-08-04 21:57:05 【问题描述】:

使用播放框架 2.4。我通过提供我自己的 SSLEngineProvider 实现打开了需要的客户端证书。但我只是找不到从控制器获取客户端证书的方法。我会满足于底层套接字,但我也找不到访问它的方法。

【问题讨论】:

【参考方案1】:

好的。首先,没有可以访问的 SSL 套接字。 Netty 进行自己的 SSL 处理,并且不为此使用 javax.net.ssl.SSLSocket

做我需要的事情并非易事,而且 Play 根本不支持。我听到的答案是“我们通过一些钩子来做到这一点”(我从未见过任何代码,我的理解是这需要破解 Play 或 Netty),或者“在它到达 Play 之前终止 SSL”(那个是最重要的) - “SSL 在播放中很慢,所以无论如何你都应该这样做”)。由于我创建了自己的 SSL 引擎,因此我尝试将引擎与请求相关联,但是引擎实例化是在 I/O 线程上完成的,其中请求实例化是在工作线程上完成的,所以我找不到同步的方法他们起来。

我提出了使用反射的解决方案,并且仅适用于特定(我想是)Play 版本。它适用于 2.4.2。我使用 IDEA 调试器向下查找活动对象以查找我正在寻找的信息。

public class CheckMessage 

    private static Field extract1;
    private static Field extract2;
    private static Field extract3;
    private static Field extract4;
    private static Field extract5;
    private static Field extract6;
    private static Field extract7;
    private static Field extract8;

    public static SSLEngine getSSLEngine() 

        try 

            Http.Request req = Controller.request();

            Field f = extract1;
            if (f == null) 
                extract1 = f = Class.forName("play.core.j.RequestHeaderImpl").getDeclaredField("header");
                f.setAccessible(true);
            

            Object aux = f.get(req);

            f = extract2;
            if (f == null) 
                extract2 = f = aux.getClass().getDeclaredField("rh$1");
                f.setAccessible(true);
            
            aux = f.get(aux);

            f = extract3;
            if (f == null) 
                extract3 = f = aux.getClass().getDeclaredField("_remoteAddress$1");
                f.setAccessible(true);
            
            aux = f.get(aux);

            f = extract4;
            if (f == null) 
                extract4 = f = aux.getClass().getDeclaredField("rh$1");
                f.setAccessible(true);
            
            aux = f.get(aux);

            f = extract5;
            if (f == null) 
                extract5 = f = aux.getClass().getDeclaredField("e$1");
                f.setAccessible(true);
            
            aux = f.get(aux);

            f = extract6;
            if (f == null) 
                extract6 = f = aux.getClass().getSuperclass().getDeclaredField("channel");
                f.setAccessible(true);
            
            aux = f.get(aux);

            f = extract7;
            if (f == null) 
                extract7 = f = aux.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("pipeline");
                f.setAccessible(true);
            

            DefaultChannelPipeline dpc = (DefaultChannelPipeline) f.get(aux);

            aux = dpc.get("ssl");
            if (aux == null)  return null; 

            f = extract8;
            if (f == null) 
                extract8 = f = aux.getClass().getDeclaredField("engine");
                f.setAccessible(true);
            

            return (SSLEngine) f.get(aux);

         catch (Exception e) 
            throw new RuntimeException();
        

    

【讨论】:

以上是关于在play framework 2.4中,如何访问ssl socket(或ssl client cert)的主要内容,如果未能解决你的问题,请参考以下文章

Play Framework 2.4 在 Scala 模板中使用注入变量

如何使用 Jenkins 在本地自动部署 Play Framework (2.4) 应用程序?

如何将模块添加到 Play!框架 2.4

如何将 CDN 与 Play Framework 2.4 资产一起使用?

Play Framework 2.4 发送邮件

Play Framework 2.4 全局对象迁移