Đây là giải pháp, dựa trên ví dụ về máy chủ HttpSnoop từ dự án netty.
Khi thiết lập các đường ống dẫn phía khách hàng, động cơ ssl phải được thiết lập như sau:
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;
}
}
Sau đó SSLContext của bạn phải được sửa đổi như sau để thiết lập một cửa hàng tin tưởng, thêm vào một keystore (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
}
}
Tôi muốn nhận xét về câu trả lời của CStepnitz. Từ tài liệu SslEngine: Định cấu hình công cụ để yêu cầu xác thực ứng dụng khách. Tùy chọn này chỉ hữu ích cho các công cụ ở chế độ máy chủ. Không phải là phía khách hàng như ông đã chỉ ra. – user1792307
@CStepnitz: Bạn có biết những loại chứng chỉ mà TrustManager sẽ chấp nhận không? Tôi có kiến trúc rất giống nhau nhưng khách hàng đang gửi một chứng nhận ECC (và cái bắt tay thất bại vì đường cong trên chứng nhận không được công nhận) nhưng các chứng chỉ RSA được chấp nhận. – favicon