1. 程式人生 > >基於 MINA 的 TLS/SSL NIO Socket 實現(二)

基於 MINA 的 TLS/SSL NIO Socket 實現(二)

MinaSocketApache.netSecurity 
功能:1) 客戶端首先必須以普通連線方式連線連線伺服器
     2) 伺服器接收到連線後,通知客戶端啟用TLS/SSL方式連線
     3) 雙方都啟用成功後,通過資料加密方式完成資訊的通訊
備註: TLS/SSL 實現是基於 MINA 的官方例子
地址: http://mina.apache.org/


客戶端和伺服器端通訊內容:
客戶端:HELLO
伺服器:Hello SSL
客戶端:Client SSL Finished
伺服器:Server SSL Finished
客戶端:資訊保安嗎?
伺服器:資訊保安!
客戶端:lawless command(非法的命令)
伺服器:No Support Command(伺服器響應不支援此命令)


伺服器端程式碼:
Java程式碼  收藏程式碼
package com.sariel.tls.server;  
  
import java.net.InetSocketAddress;  
import java.nio.charset.Charset;  
  
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;  
import org.apache.mina.filter.codec.ProtocolCodecFilter;  
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;  
import org.apache.mina.transport.socket.SocketAcceptor;  
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;  
  
public class TempTLSServer {  
    private static final int PORT = 50003;  
  
    public static void main(String[] args) throws Exception {  
          
        SocketAcceptor acceptor = new NioSocketAcceptor();  
        acceptor.setReuseAddress(true);  
          
        DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();  
          
        chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));  
          
        acceptor.setHandler(new TempTLSServerHandler());  
          
        acceptor.bind(new InetSocketAddress(PORT));  
        System.out.println("伺服器在 [" + PORT + "] 等待連線...");  
    }  
}  


Java程式碼  收藏程式碼
package com.sariel.tls.server;  
  
import org.apache.mina.core.service.IoHandlerAdapter;  
import org.apache.mina.core.session.IdleStatus;  
import org.apache.mina.core.session.IoSession;  
import org.apache.mina.filter.ssl.SslFilter;  
import org.apache.mina.filter.ssl.SslFilter.SslFilterMessage;  
  
import com.sariel.tls.BogusSslContextFactory;  
  
public class TempTLSServerHandler extends IoHandlerAdapter {  
    public void sessionCreated(IoSession session) throws Exception {  
        System.out.println("[NIO Server]>> sessionCreated");  
          
        session.setAttribute(SslFilter.USE_NOTIFICATION);  
    }  
  
    public void sessionOpened(IoSession session) throws Exception {  
        System.out.println("[NIO Server]>> sessionOpened");  
    }  
  
    public void sessionClosed(IoSession session) throws Exception {  
        System.out.println("[NIO Server]>> sessionClosed");  
    }  
  
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {  
        System.out.println("[NIO Server]>> sessionIdle");  
    }  
  
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {  
        System.out.println("[NIO Server]>> exceptionCaught :");  
        cause.printStackTrace();  
    }  
  
    public void messageReceived(IoSession session, Object message) throws Exception {  
        System.out.println("[NIO Server]>> messageReceived");  
        String msg = "";  
        if (message instanceof SslFilterMessage) {  
            msg = ((SslFilterMessage) message).toString();  
        } else {  
            msg = (String) message;  
        }  
        System.out.println("[NIO Server Received]>> : " + msg);  
        if ("Hello".equalsIgnoreCase(msg)) {  
            session.write("Hello SSL");  
        } else if ("Client SSL Finished".equalsIgnoreCase(msg)) {  
            session.getFilterChain().addFirst("SSL", new SslFilter(BogusSslContextFactory.getInstance(true)));  
            // ((SslFilter)session.getFilterChain().get("SSL")).startSsl(session);  
            session.write("Server SSL Finished");  
        } else if ("資訊保安嗎?".equals(msg)) {  
            session.write("資訊保安!");  
        } else {  
            session.write("No Support Command");  
        }  
    }  
  
    public void messageSent(IoSession session, Object message) throws Exception {  
        System.out.println("[NIO Server]>> messageSent");  
        System.out.println("[NIO Server messageSent]>> : " + (String) message);  
    }  
  
}  


客戶端程式碼:
Java程式碼  收藏程式碼
package com.sariel.tls.client;  
  
import java.net.InetSocketAddress;  
import java.nio.charset.Charset;  
import java.security.GeneralSecurityException;  
  
import org.apache.mina.core.future.ConnectFuture;  
import org.apache.mina.core.service.IoConnector;  
import org.apache.mina.core.session.IoSession;  
import org.apache.mina.filter.codec.ProtocolCodecFilter;  
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;  
import org.apache.mina.transport.socket.nio.NioSocketConnector;  
  
public class TempTLSClient {  
  
    private static final int PORT = 50003;  
  
    private static final String TARGET_IP = "192.168.12.41";  
  
    public static void main(String[] args) throws GeneralSecurityException {  
          
        IoConnector connector = new NioSocketConnector();  
          
        connector.setHandler(new TempTLSClientHandler());  
          
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));  
          
        ConnectFuture future = connector.connect(new InetSocketAddress(TARGET_IP, PORT));  
          
        future.awaitUninterruptibly();  
          
        IoSession session = future.getSession();  
          
        session.write("HELLO");  
          
        session.getCloseFuture().awaitUninterruptibly();  
        connector.dispose();  
    }  
}  


Java程式碼  收藏程式碼
package com.sariel.tls.client;  
  
import org.apache.mina.core.service.IoHandlerAdapter;  
import org.apache.mina.core.session.IdleStatus;  
import org.apache.mina.core.session.IoSession;  
import org.apache.mina.filter.ssl.SslFilter;  
  
import com.sariel.tls.BogusSslContextFactory;  
  
public class TempTLSClientHandler extends IoHandlerAdapter {  
    public void sessionCreated(IoSession session) throws Exception {  
        System.out.println("[NIO Client]>> sessionCreated");  
    }  
  
    public void sessionOpened(IoSession session) throws Exception {  
        System.out.println("[NIO Client]>> sessionOpened");  
    }  
  
    public void sessionClosed(IoSession session) throws Exception {  
        System.out.println("[NIO Client]>> sessionClosed");  
    }  
  
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {  
        System.out.println("[NIO Client]>> sessionIdle");  
    }  
  
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {  
        System.out.println("[NIO Client]>> exceptionCaught :");  
        cause.printStackTrace();  
    }  
  
    public void messageReceived(IoSession session, Object message) throws Exception {  
        System.out.println("[NIO Client]>> messageReceived");  
        System.out.println("[NIO Client Received]>>" + (String) message);  
        if ("Hello SSL".equals((String) message)) {  
            session.write("Client SSL Finished");  
        } else if ("Server SSL Finished".equals((String) message)) {  
            session.write("資訊保安嗎?");  
        } else if ("資訊保安!".equals((String) message)) {  
            session.write("lawless command");  
        }  
    }  
  
    public void messageSent(IoSession session, Object message) throws Exception {  
        System.out.println("[NIO Client]>> messageSent");  
        System.out.println("[NIO Client messageSent]>> : " + (String) message);  
        if ("Client SSL Finished".equals((String) message)) {  
            SslFilter connectorTLSFilter = new SslFilter(BogusSslContextFactory.getInstance(false));  
            connectorTLSFilter.setUseClientMode(true);  
            session.getFilterChain().addFirst("SSL", connectorTLSFilter);  
            // ((SslFilter)session.getFilterChain().get("SSL")).startSsl(session);  
        }  
    }  
}  


建立 KEY 檔案指令:keytool -genkey -alias bogus -keysize 512 -validity 3650 -keyalg RSA -dname "CN=bogus.com, OU=XXX CA,O=Bogus Inc, L=Stockholm, S=Stockholm, C=SE" -keypass boguspw -storepass boguspw -keystore bogus.cert
(在 Java 原始檔 BogusSslContextFactory.java 中也有,是官方的)