`
raymond.chen
  • 浏览: 1418782 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

SSL安全Socket范例

 
阅读更多

    在使用Socket编写通讯程序时,通过添加对SSL的支持可以保障数据的安全和完整。Java提供了Java 安全套接字扩展——JSSE,JSSE是一个纯Java实现的SSL和TLS协议框架,抽象了SSL和TLS复杂的算法,使安全问题变得简单。使用JSSE来开发安全的Socket通讯程序需要一个证书来进行安全认证,认证支持单向认证和双向认证两种方式。

 

    在编写通讯程序之前,需要先生成证书。这里使用java自带的keytool工具生成证书。

        服务端证书:

            创建服务端keystore

                keytool -genkey -keystore server.jks -storepass 123456 -keyalg RSA -validity 365 -keypass 123456

 

            导出服务端证书

                keytool -export -keystore server.jks -storepass 123456 -file server.cer

 

            将服务端证书导入到客户端trustkeystroe

                keytool -import -keystore server_clientTrust.jks -storepass 123456 -file server.cer

 

        客户端证书:

            创建客户端keystore

                keytool -genkey -keystore client.jks -storepass 123456 -keyalg RSA -validity 365 -keypass 123456

 

            导出客户端证书

                keytool -export -keystore client.jks -storepass 123456 -file client.cer

 

            将客户端证书导入到服务端trustkeystroe

                keytool -import -keystore client_serverTrust.jks -storepass 123456 -file client.cer

 

        -keystore:指定密钥库的名称

        -storepass:指定密钥库的密码

        -keyalg:指定密钥的算法,默认值为DSA

        -validity:指定创建的证书有效期多少天(默认 90)

        -keypass:指定私钥的密码

 

 以下是范例源码:

    SSLBese源码:

public class SSLBese {
	protected static final int SERVER_PORT = 5900;

	protected static final String SERVER_JKS_FILE = "certificate/server.jks";
	protected static final String SERVER_TRUST_JKS_FILE = "certificate/serverTrust.jks";
	
	protected static final String CLIENT_JKS_FILE = "certificate/client.jks";
	protected static final String CLIENT_TRUST_JKS_FILE = "certificate/clientTrust.jks";
	
	protected static final String STOREPASS = "123456";	//密钥库的密码
	protected static final String KEYPASS = "123456";	//私钥的密码
	
	protected static int AUTH_MODULE = 2;	//认证模式:0-非SSL认证,1-单向SSL认证,2-双向SSL认证
	
	protected String read(InputStream is) throws Exception {
		BufferedInputStream in = new BufferedInputStream(is);
        byte[] buffer = new byte[1024];
        in.read(buffer);
        return new String(buffer, "UTF-8");
	}
	
	protected void write(OutputStream os, String msg) throws Exception {
		BufferedOutputStream out = new BufferedOutputStream(os);
        out.write(msg.getBytes("UTF-8"));  
        out.flush();
	}
}

  

    SSLServer源码:

public class SSLServer extends SSLBese{
	private ServerSocket serverSocket;
	
	public void start(){
        try {
    		init();
    		
            Socket socket = serverSocket.accept();
            
            String remoteAddress = socket.getRemoteSocketAddress().toString();
            System.out.println("客户端连接:" + remoteAddress);
    		
    		while (true) {
				//read
				String recMsg = read(socket.getInputStream());
				System.out.println(recMsg);

    			//write
				String msg = "Server received!";
				write(socket.getOutputStream(), msg);
            } 
    		
        } catch (Exception ex) {  
            ex.printStackTrace();  
        }
	}
	
	private void init() throws Exception {
		if(serverSocket != null){
			serverSocket.close();
			serverSocket = null;
		}
		
		if(AUTH_MODULE == 0){
			createServerSocket();
		}else{
			createSSLServerSocket();
		}
		
        System.out.println("启动监听服务[" + SERVER_PORT + "] ...");
	}
	
	private void createServerSocket() throws Exception {
		serverSocket = new ServerSocket();
		serverSocket.setReuseAddress(true);
		serverSocket.bind(new InetSocketAddress(SERVER_PORT));
	}

	private void createSSLServerSocket() throws Exception {
		//服务端私钥
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");		//创建密钥管理器
        KeyStore ks = KeyStore.getInstance("JKS");	//创建密钥库
        ks.load(new FileInputStream(SERVER_JKS_FILE), STOREPASS.toCharArray()); //加载私钥  
        keyManagerFactory.init(ks, STOREPASS.toCharArray());
        KeyManager[] kms = keyManagerFactory.getKeyManagers();
        
        //客户端的授权证书(客户端公钥)
        TrustManager[] tms = null;
        if(AUTH_MODULE == 2){
	        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");	//信任管理器
	        KeyStore tks = KeyStore.getInstance("JKS");
	        tks.load(new FileInputStream(CLIENT_TRUST_JKS_FILE), STOREPASS.toCharArray());
	        trustManagerFactory.init(tks);  
	        tms = trustManagerFactory.getTrustManagers();
        }
        
		SSLContext ctx = SSLContext.getInstance("TLSV1"); 
        ctx.init(kms, tms, null);
        
        serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket();
        ((SSLServerSocket)serverSocket).setEnabledCipherSuites(((SSLServerSocket)serverSocket).getSupportedCipherSuites());
        ((SSLServerSocket)serverSocket).setUseClientMode(false);
        
        if(AUTH_MODULE == 2){
        	((SSLServerSocket)serverSocket).setNeedClientAuth(true); //验证客户端证书
        }else{
        	((SSLServerSocket)serverSocket).setNeedClientAuth(false);
        }
        
        serverSocket.setReuseAddress(true); //是否允许重用绑定端口
        serverSocket.bind(new InetSocketAddress(SERVER_PORT));
        
        System.out.println("启用SSL安全认证");
	}
	
	public static void main(String[] args) {
		SSLServer server = new SSLServer();
		server.start();
	}
}

  

    SSLClient源码:

public class SSLClient extends SSLBese{	
	private String serverIp;
	private int serverPort;
	private Socket socket;
	
	public SSLClient(String serverIp, int serverPort){
		this.serverIp = serverIp;
		this.serverPort = serverPort;
	}
	
	public void execute(){
		try {
			init();

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			
			while(true){
				//write
				String msg = "now time is " + sdf.format(new Date());
				write(socket.getOutputStream(), msg);
				
				//read
				String recMsg = read(socket.getInputStream());
				System.out.println(recMsg);
	            
	            TimeUnit.MILLISECONDS.sleep(1000);
			}
            
        } catch (Exception ex) {  
        	ex.printStackTrace();
        } finally {
        	if(socket != null){
        		try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
        }
	}
	
	private void init() throws Exception {
		if(AUTH_MODULE == 0){
			createSocket();
		}else{
			createSSLSocket();
		}
	}
	
	private void createSocket() throws Exception {
		socket = new Socket(); 
        socket.setKeepAlive(true);
        socket.setTcpNoDelay(true); //TCP不延迟发送
        socket.setSoLinger(true, 0); //延迟n秒关闭Socket底层连接
        socket.setSoTimeout(10000);
        socket.connect(new InetSocketAddress(this.serverIp, this.serverPort), 6000);
	}

	private void createSSLSocket() throws Exception {
		//客户端私钥
		KeyManager[] kms = null;
		if(AUTH_MODULE == 2){
	        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
	        KeyStore ks = KeyStore.getInstance("JKS");
	        ks.load(new FileInputStream(CLIENT_JKS_FILE), STOREPASS.toCharArray()); 
	        keyManagerFactory.init(ks, STOREPASS.toCharArray());  
	        kms = keyManagerFactory.getKeyManagers();
		}
		
        //服务端的授权证书(服务端公钥)
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
        KeyStore tks = KeyStore.getInstance("JKS");
        tks.load(new FileInputStream(SERVER_TRUST_JKS_FILE), STOREPASS.toCharArray());
        trustManagerFactory.init(tks);
        TrustManager[] tms = trustManagerFactory.getTrustManagers(); 
        
		SSLContext ctx = SSLContext.getInstance("TLSV1");
        ctx.init(kms, tms, null);  

        socket = (SSLSocket)ctx.getSocketFactory().createSocket();
        ((SSLSocket)socket).setEnabledCipherSuites(((SSLSocket)socket).getSupportedCipherSuites());	//可以使用所有支持的加密套件
        ((SSLSocket)socket).setUseClientMode(true);
        socket.setKeepAlive(true);
        socket.setTcpNoDelay(true);
        socket.setSoLinger(true, 0);
        socket.setSoTimeout(10000);
        socket.connect(new InetSocketAddress(this.serverIp, this.serverPort), 6000);
	}
	
	public static void main(String[] args) {
		SSLClient client = new SSLClient("127.0.0.1", SERVER_PORT);
		client.execute();
	}
	
}

  

分享到:
评论

相关推荐

    SSL双向验证范例

    eclipse中使用Jetty插件实现https请求与SSL双向验证

    openssl-1.0.0a

     SSL是Secure Socket Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。Netscape公司在推出第一个Web浏览器的同时,提出了SSL协议标准,目前已有3.0版本。SSL采用公开密钥技术。其目标是保证两个...

    OpenSSL-1_0_0d_Win32

    OpenSSL的应用程序是基于OpenSSL的密码算法库和SSL协议库写成的,所以也是一些非常好的OpenSSL的API使用范例,读懂所有这些范例,你对OpenSSL的API使用了解就比较全面了,当然,这也是一项锻炼你的意志力的工作。...

    java源码包---java 源码 大量 实例

    Java Socket 聊天通信演示代码 2个目标文件,一个服务器,一个客户端。 Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例...

    java源码包2

    Java Socket 聊天通信演示代码 2个目标文件,一个服务器,一个客户端。 Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例...

    java源码包3

    Java Socket 聊天通信演示代码 2个目标文件,一个服务器,一个客户端。 Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例...

    java源码包4

    Java Socket 聊天通信演示代码 2个目标文件,一个服务器,一个客户端。 Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例...

    JAVA上百实例源码以及开源项目

    一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源代码...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

    JAVA上百实例源码以及开源项目源代码

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

Global site tag (gtag.js) - Google Analytics