简体   繁体   English

使用 2-way SSL Handskake(客户端和服务器证书)设置 Netty

[英]Set up Netty with 2-way SSL Handskake (client and server certificate)

I am now trying to set up Netty with a 2 way SSL handshake, where both the client and server present and verify certificates.我现在正在尝试使用 2 路 SSL 握手来设置 Netty,其中客户端和服务器都提供并验证证书。

This does not appear to be implemented in SslHandler.这似乎没有在 SslHandler 中实现。 Has anyone does this?有没有人这样做? I suppose it would go in the SslHandler.handshake operation and be delegated to javax.net.ssl.SSLEngine?我想它会进入 SslHandler.handshake 操作并被委托给 javax.net.ssl.SSLEngine?

Any hints/tips/pre-existing implementations?任何提示/技巧/预先存在的实现?

Thanks!谢谢!


ANSWER (stackoverflow won't let me post it the normal way) I found that if I set the needClientAuth flag on the SSLEngine object before setting up my SslHandler, that takes care of the problem!答案(stackoverflow 不会让我以正常方式发布它)我发现如果我在设置 SslHandler 之前在 SSLEngine 对象上设置了 needClientAuth 标志,那么问题就解决了!

Here is the solution, based on the HttpSnoop server example from the netty project.这是基于 netty 项目中的 HttpSnoop 服务器示例的解决方案。

When setting up the client side pipeline, the ssl engine must be set as follows:设置客户端管道时,ssl引擎必须设置如下:

public ChannelPipeline getPipeline() throws Exception {
    // Create a default pipeline implementation.
    ChannelPipeline pipeline = pipeline();

    // Uncomment the following line if you want HTTPS
    SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
    engine.setUseClientMode(false);
    engine.setNeedClientAuth(true);
    pipeline.addLast("ssl", new SslHandler(engine));

    pipeline.addLast("decoder", new HttpRequestDecoder());
    pipeline.addLast("logger", new RequestAuditLogger());
    // Uncomment the following line if you don't want to handle HttpChunks.
    pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
    pipeline.addLast("outputLogger", new ResponseAuditLogger());
    pipeline.addLast("encoder", new HttpResponseEncoder());
    // Remove the following line if you don't want automatic content compression.
    pipeline.addLast("deflater", new HttpContentCompressor());
    pipeline.addLast("handler", new HttpSnoopServerHandler());
    return pipeline;
}
}

Then your SSLContext must be modified as follows to set up a trust store in addition to a keystore (SecureChatSslContextFactory):然后您的 SSLContext 必须按如下方式修改以设置除了密钥库(SecureChatSslContextFactory)之外的信任库:

public final class SecureChatSslContextFactory {


private static Logger logger = LoggerFactory.getLogger(SecureChatSslContextFactory.class);

private static final String PROTOCOL = "TLS";
private static final SSLContext SERVER_CONTEXT;
private static final SSLContext CLIENT_CONTEXT;

static {

    SSLContext serverContext = null;
    SSLContext clientContext = null;

        // get keystore and trustore locations and passwords
    String keyStoreLocation = System.getProperty("javax.net.ssl.keyStore");
    String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
    String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore");
    String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
    try {

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(KeyStoreStreamManager.asInputStream(keyStoreLocation),
                keyStorePassword.toCharArray());

        // Set up key manager factory to use our key store
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, keyStorePassword.toCharArray());

          // truststore
        KeyStore ts = KeyStore.getInstance("JKS");
        ts.load(KeyStoreStreamManager.asInputStream(trustStoreLocation),
                trustStorePassword.toCharArray());

        // set up trust manager factory to use our trust store
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ts);

        // Initialize the SSLContext to work with our key managers.
        serverContext = SSLContext.getInstance(PROTOCOL);
        serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

    } catch (Exception e) {
        throw new Error(
                "Failed to initialize the server-side SSLContext", e);
    }

    try {
        clientContext = SSLContext.getInstance(PROTOCOL);
        clientContext.init(null, SecureChatTrustManagerFactory.getTrustManagers(), null);
    } catch (Exception e) {
        throw new Error(
                "Failed to initialize the client-side SSLContext", e);
    }

    SERVER_CONTEXT = serverContext;
    CLIENT_CONTEXT = clientContext;
}

public static SSLContext getServerContext() {
    return SERVER_CONTEXT;
}

public static SSLContext getClientContext() {
    return CLIENT_CONTEXT;
}

private SecureChatSslContextFactory() {
    // Unused
}
}

Instead of setting SSLEngine use nettys SslContext to create a new SslHandler .而不是设置SSLEngine使用 nettys SslContext创建一个新的SslHandler Basically you can create new SslContext by passing KeyManagerFactory as follows基本上你可以通过传递KeyManagerFactory来创建新的SslContext如下

SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory).build(); SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory).build();

Then use created SslContext to get the handler for ChannelPipeline .然后使用创建的SslContext来获取ChannelPipeline的处理程序。

ChannelPipeline.addLast("ssl", sslContext.newHandler(socketChannel.alloc())); ChannelPipeline.addLast("ssl", sslContext.newHandler(socketChannel.alloc()));

Mutual authentication is now supported by SslContext (currently just for JDK provider, but OpenSSL provide support is coming soon). SslContext现在支持相互认证(目前仅适用于 JDK 提供者,但 OpenSSL 提供支持即将推出)。 See newClientContext and newServerContext which both now support taking a TrustManagerFactory and a KeyManagerFactory.请参阅newClientContextnewServerContext ,它们现在都支持采用 TrustManagerFactory 和 KeyManagerFactory。 These static factory methods also support directly taking certificate, key, and certificate chain files to build the TrustManagerFactory and KeyManagerFactory for you.这些静态工厂方法还支持直接获取证书、密钥和证书链文件来为您构建 TrustManagerFactory 和 KeyManagerFactory。

See the JdkSslEngineTest for an example of how to require client authentication (for the JDK provider).有关如何要求客户端身份验证(对于 JDK 提供程序)的示例,请参阅JdkSslEngineTest

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用带有SSL证书的Netty的简单方法? - Simple way of using netty with ssl certificate? 我的 SSL 客户端 (Java) 未通过双向 SSL 握手将证书发送回服务器 - My SSL client (Java) isn't sending a certificate back to the server in two-way SSL handshake 我找到了一个使用Web服务的https客户端; 该客户端使用的是2向SSL还是1向SSL? - I found an https client to consume webservice; is this client is using 2-way or 1-way SSL? SSL客户端(Java)不在两次SSL握手中将证书发送回服务器 - SSL client (Java) is not sending a certificate back to the server in two-way SSL handshake 如何使用openssl在tomcat 7上的客户端和服务器上配置两种方式的ssl以生成ssl证书? - How to configure two way ssl on client and server on tomcat 7 using openssl for ssl certificate generation? Java如何建立SSL连接客户端服务器 - Java how to set up SSL Connection client-server JBoss 1路和2路SSL同时使用 - JBoss 1-way and 2-way SSL symultaneously 如何编写同时处理1路和2路SSL的通用Java客户端? - How to write a generic java client handling both 1-way and 2-way ssl? Apache Thrift 2路SSL相互认证 - Apache Thrift 2-way SSL mutual authentication AWS Lambda 中的相互身份验证(2 路 SSL) - Mutual Authentication (2-way SSL) in AWS Lambda
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM