在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) 应用程序?