Certificates and code generation operation about passwords, modify into their own in accordance with your own needs
Use keytool to generate a certificate
This command is usually JDK \ jre \ lib \ security \ directory operations
keytool commonly used commands
parameter | DEFINITIONS |
---|---|
-alias | Alias certificate |
-keystore | Name of the certificate library |
-storepass | Password certificate store |
-keypass | Password certificate |
-list | Display certificate information keystore |
-v | Display certificate keystore details |
-export | Display certificate information keystore |
-file | Specify export certificate file name and path |
-delete | To delete an entry key store |
-import | The signed digital certificate into the key store |
-keypasswd | Modify keystore password specified entry |
-dname | Specify the certificate owner information |
-Keylg | Algorithm specified key |
-validity | Specifies the number of days to create the certificate is valid |
-keysize | Specifying a key length |
Specific operations to generate a certificate
- Create a server-side keys
keytool -genkey -alias nettyServer -keysize 1024 -validity 3650 -keyalg RSA -dname "CN=localhost" -keypass 证书密码 -storepass 服务端的证书仓库密码 -keystore serverCerts.jks
- Export server keys
keytool -export -alias nettyServer -keystore serverCerts.jks -storepass 服务端的证书仓库密码 -file serverCert.cer
- Creating client keys
keytool -genkey -alias nettyClient -keysize 1024 -validity 3650 -keyalg RSA -dname "CN=PF,OU=YJC,O=YJC,L=BJ,S=BJ,C=ZN" -keypass 证书密码 -storepass 客户端的证书仓库密码 -keystore clientCerts.jks
- Export client keys
keytool -export -alias nettyClient -keystore clientCerts.jks -file nettyclientCert.cer -storepass 客户端的证书仓库密码
- The client's certificate into the trusted certificate in warehouse server
keytool -import -trustcacerts -alias smcc -file nettyClientCert.cer -storepass 服务端的证书仓库密码 -keystore serverCerts.jks
- The service side of the import certificate to a trusted certificate in the client's warehouse
keytool -import -trustcacerts -alias smccClient -file serverCert.cer -storepass 客户端的证书仓库密码 -keystore clientCerts.jks
Server create ContextSSLFactory
package com.yjc.rpc.ssl;
import org.springframework.core.io.ClassPathResource;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.*;
public class ContextSSLFactory {
private static final SSLContext SSL_CONTEXT_S ;
static{
SSLContext sslContextServer = null ;
try {
sslContextServer = SSLContext.getInstance("SSLv3") ;
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
try{
if(getKeyManagersServer() != null && getTrustManagersServer() != null ){
sslContextServer.init(getKeyManagersServer(), getTrustManagersServer(), null);
}
}catch(Exception e){
e.printStackTrace() ;
}
sslContextServer.createSSLEngine().getSupportedCipherSuites() ;
SSL_CONTEXT_S = sslContextServer ;
}
public ContextSSLFactory(){
}
public static SSLContext getSslContext(){
return SSL_CONTEXT_S ;
}
/**
* 获取服务端信任的证书
* @param: @return
* @return: TrustManager[]
* @throws
*/
private static TrustManager[] getTrustManagersServer(){
FileInputStream is = null ;
TrustManager[] trustManagersw=null;
TrustManagerFactory trustManagerFactory=null;
KeyStore ks=null;
try {
trustManagerFactory = TrustManagerFactory.getInstance("SunX509") ;
is =is =new FileInputStream( (new ClassPathResource("certs/serverCerts.jks")).getFile() );
String keyStorePass = "服务端的证书仓库密码" ;
ks=KeyStore.getInstance("JKS");
ks.load(is,keyStorePass.toCharArray());
trustManagerFactory.init(ks);
trustManagersw=trustManagerFactory.getTrustManagers();
} catch (Exception e) {
e.printStackTrace();
}
finally{
if(is != null ){
try {
is.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return trustManagersw;
}
/**
* 获取keymanager列表
* @param: @return
* @return: KeyManager[]
* @throws
*/
private static KeyManager[] getKeyManagersServer(){
FileInputStream is = null ;
KeyStore ks = null ;
KeyManagerFactory keyFac = null ;
KeyManager[] kms = null ;
try {
// 获得KeyManagerFactory对象. 初始化位默认算法
keyFac = KeyManagerFactory.getInstance("SunX509") ;
// String keyStorePath = PropertyUtil.getProperty("httpsKeyStorePath");
is =new FileInputStream( (new ClassPathResource("certs/serverCerts.jks")).getFile() );
ks = KeyStore.getInstance("JKS") ;
String keyStorePass = "服务端的证书仓库密码";
ks.load(is , keyStorePass.toCharArray()) ;
keyFac.init(ks, keyStorePass.toCharArray()) ;
kms = keyFac.getKeyManagers() ;
} catch (Exception e) {
e.printStackTrace();
}
finally{
if(is != null ){
try {
is.close() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return kms ;
}
}
Add netty comes sslHandler in the pipeline
It should be noted that SslHandler needs to be added to the front of the pipeline, or even added, unlawful client can connect as normal
try {
//设置事件处理
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
// 添加心跳支持
pipeline.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));
// 基于定长的方式解决粘包/拆包问题
// pipeline.addLast(new LengthFieldBasedFrameDecoder(nettyConfig.getMaxFrameLength()
// , 0, 2, 0, 2));
// pipeline.addLast(new LengthFieldPrepender(2));
// 序列化
// pipeline.addLast(new MessagePackDecoder());
// pipeline.addLast(new MessagePackEncoder());
pipeline.addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
pipeline.addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
pipeline.addLast(channelHandlerAdapter);
SSLEngine engine = ContextSSLFactory.getSslContext().createSSLEngine();
engine.setUseClientMode(false); //设置为服务端模式
engine.setNeedClientAuth(true); //需要验证客户端
pipeline.addFirst("ssl", new SslHandler(engine)); //这个handler需要加到最前面
}
});
LOGGER.info("netty服务器在[{}]端口启动监听", port);
ChannelFuture f = serverBootstrap.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
LOGGER.info("[出现异常] 释放资源");
boss.shutdownGracefully();
work.shutdownGracefully();
}
The client code is basically similar, there is not posted.