zoukankan      html  css  js  c++  java
  • Java SSLSocket

    Java SSLSocket

           JSSE(Java Security Socket Extension)是Sun公司为了解决互联网信息安全传输提出的一个解决方案,它实现了SSL和TSL协议,包含了数据加密、服务器验证、消息完整性和客户端验证等技术。通过使用JSSE简洁的API,可以在客户端和服务器端之间通过SSL/TSL协议安全地传输数据。

    1、生成证书
          需要将OpenSSL生成根证书CA及签发子证书一文中生成的客户端及服务端私钥和数字证书进行导出,生成Java环境可用的keystore文件。
    (1)客户端私钥与证书的导出:

    openssl pkcs12 -export -clcerts -name www.mydomain.com 
    -inkey private/client-key.pem -in certs/client.cer -out certs/client.keystore
    

    (2)服务器端私钥与证书的导出:

    openssl pkcs12 -export -clcerts -name www.mydomain.com 
    -inkey private/server-key.pem -in certs/server.cer -out certs/server.keystore
    

    (3)之后,便会在certs文件夹下生成ca-trust.keystore文件。加上上面生成的server.keystore和client.keystore,certs下会生成这三个文件:

    2、Java实现的SSL通信客户端

    package com.demo.ssl;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.security.KeyStore;
    
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.TrustManagerFactory;
    
    public class SSLClient {
    	private SSLSocket sslSocket;
    	public static void main(String[] args) throws Exception {
    		SSLClient client = new SSLClient();
    		client.init();
    		System.out.println("SSLClient initialized.");
    		client.process();
    	}
    	
    	//客户端将要使用到client.keystore和ca-trust.keystore
    	public void init() throws Exception {
    		String host = "127.0.0.1";
    		int port = 1234;
    		String keystorePath = "/home/user/CA/certs/client.keystore";
    		String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore";
    		String keystorePassword = "abc123_";
    		SSLContext context = SSLContext.getInstance("SSL");
    		//客户端证书库
    		KeyStore clientKeystore = KeyStore.getInstance("pkcs12");
    		FileInputStream keystoreFis = new FileInputStream(keystorePath);
    		clientKeystore.load(keystoreFis, keystorePassword.toCharArray());
    		//信任证书库
    		KeyStore trustKeystore = KeyStore.getInstance("jks");
    		FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath);
    		trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray());
    		
    		//密钥库
    		KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
    		kmf.init(clientKeystore, keystorePassword.toCharArray());
    
    		//信任库
    		TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
    		tmf.init(trustKeystore);
    		
    		//初始化SSL上下文
                    SSLContext context = SSLContext.getInstance("SSL");
    		context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    		
    		sslSocket = (SSLSocket)context.getSocketFactory().createSocket(host, port);
    	}
    	
    	public void process() throws Exception {
    		//往SSLSocket中写入数据
    		String hello = "hello boy!";
    		OutputStream out = sslSocket.getOutputStream();
    		out.write(hello.getBytes(), 0, hello.getBytes().length);
    		out.flush();
    		
    		//从SSLSocket中读取数据
    		InputStream in = sslSocket.getInputStream();
    		byte[] buffer = new byte[50];
    		in.read(buffer);
    		System.out.println(new String(buffer));
    	}
    }
    

          初始化时,首先取得SSLContext、KeyManagerFactory、TrustManagerFactory实例,然后加载客户端的密钥库和信任库到相应的KeyStore,对KeyManagerFactory和TrustManagerFactory进行初始化,最后用KeyManagerFactory和TrustManagerFactory对SSLContext进行初始化,并创建SSLSocket。

    3、Java实现的SSL通信服务器端

    package com.demo.ssl;
    
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.security.KeyStore;
    
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocket;
    import javax.net.ssl.TrustManagerFactory;
    
    public class SSLServer {
    	private SSLServerSocket sslServerSocket;
    	public static void main(String[] args) throws Exception {
    		SSLServer server = new SSLServer();
    		server.init();
    		System.out.println("SSLServer initialized.");
    		server.process();
    	}
    	
    	//服务器端将要使用到server.keystore和ca-trust.keystore
    	public void init() throws Exception {
    		int port = 1234;
    		String keystorePath = "/home/user/CA/certs/server.keystore";
    		String trustKeystorePath = "/home/user/CA/certs/ca-trust.keystore";
    		String keystorePassword = "abc123_";
    		SSLContext context = SSLContext.getInstance("SSL");
    		
    		//客户端证书库
    		KeyStore keystore = KeyStore.getInstance("pkcs12");
    		FileInputStream keystoreFis = new FileInputStream(keystorePath);
    		keystore.load(keystoreFis, keystorePassword.toCharArray());
    		//信任证书库
    		KeyStore trustKeystore = KeyStore.getInstance("jks");
    		FileInputStream trustKeystoreFis = new FileInputStream(trustKeystorePath);
    		trustKeystore.load(trustKeystoreFis, keystorePassword.toCharArray());
    		
    		//密钥库
    		KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
    		kmf.init(keystore, keystorePassword.toCharArray());
    
    		//信任库
    		TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
    		tmf.init(trustKeystore);
    		
    		//初始化SSL上下文
                    SSLContext context = SSLContext.getInstance("SSL");
    		context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    		//初始化SSLSocket
    		sslServerSocket = (SSLServerSocket)context.getServerSocketFactory().createServerSocket(port);
    		//设置这个SSLServerSocket需要授权的客户端访问
    		sslServerSocket.setNeedClientAuth(true);
    	}
    	
    	public void process() throws Exception {
    		String bye = "Bye!";
    		byte[] buffer = new byte[50];
    		while(true) {
    			Socket socket = sslServerSocket.accept();
    			InputStream in = socket.getInputStream();
    			in.read(buffer);
    			System.out.println("Received: " + new String(buffer));
    			OutputStream out = socket.getOutputStream();
    			out.write(bye.getBytes());
    			out.flush();
    		}
    	}
    }
    

          先运行服务器端,再运行客户端。服务器端执行结果:

          客户端执行结果:




    参考博客:
    [1]Java使用SSLSocket通信
    [2]Java实现SSL双向认证的方法

  • 相关阅读:
    使用 yo 命令行向导给 SAP UI5 应用添加一个新的视图
    SAP Fiori Elements 应用的 manifest.json 文件运行时如何被解析的
    SAP UI5 标准应用的多语言支持
    微软 Excel 365 里如何设置下拉菜单和自动高亮成指定颜色
    SAP Fiori Elements 应用里的 Title 显示的内容是从哪里来的
    本地开发好的 SAP Fiori Elements 应用,如何部署到 ABAP 服务器上?
    如何在 Cypress 测试代码中屏蔽(Suppress)来自应用代码报出的错误消息
    教你一招:让集群慢节点无处可藏
    应用架构步入“无服务器”时代 Serverless技术迎来新发展
    MySQL数据库事务隔离性的实现
  • 原文地址:https://www.cnblogs.com/shujk/p/13800498.html
Copyright © 2011-2022 走看看