Java SSL Socket通讯示例

上一篇《OpenSSL与KeyStore指令小集》里面说到,最近研究SSL加密,会给出一个Java的小示例。复制一份可以运行的代码到生产上是非常不负责任的行为,不过小示例可以带我们入门,快速看清事物的本质。罗马不是一天建成的。

本文将给出一个Java SSL Socket的小例子,包括了Server和Client。希望大家上手之后,要多去研究相关的资料,理解基础概念。Java的优点是封装得比较彻底,需要介入的地方比较少,缺点是随着Java版本的升级和发展,会有很多新的概念和类涌出来,都要搞清楚要费不少力,另外代码量也比较大(生产级别的代码)。

具体代码

从最简单来说,Java里面只需要配置几个系统属性,创建及调用几个SSL相关的对象即可。这四个属性分别是:

  • javax.net.ssl.keyStore
    本方的密码,证书等存放地点(KeyStore文件地址)。
  • javax.net.ssl.keyStorePassword
    KeyStore的密码。没有密码可以不填。
  • javax.net.ssl.trustStore
    受信任证书的存放地点(TrustKeyStore文件地址)。
  • javax.net.ssl.trustStorePassword
    TrustKeyStore的密码。没有密码可以不填。

KeyStore类型默认是JKS类型的,不是的话,还需要设置 javax.net.ssl.keyStoreType和javax.net.ssl.trustStoreType。

Server端代码

每一次收新的连接,都新开一个线程接待。生产上请用线程池等技术。更推荐用Netty或Mina等框架处理。

public class SslServer {
		public static void main(String[] args) throws Exception {
			System.setProperty("javax.net.debug", "ssl,handshake");

			System.setProperty("javax.net.ssl.keyStore", "./cfg/server.jks");
			System.setProperty("javax.net.ssl.keyStorePassword", "123456");
			System.setProperty("javax.net.ssl.trustStore", "./cfg/clienttrust.jks");
			System.setProperty("javax.net.ssl.trustStorePassword", "123456");

			SSLServerSocketFactory serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory
					.getDefault();
			SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory
					.createServerSocket(9100);
			// 要求客户端身份验证
			serverSocket.setNeedClientAuth(true);

			while (true) {
				SSLSocket socket = (SSLSocket) serverSocket.accept();
				Accepter accepter = new Accepter(socket);
				accepter.service();
			}
		}

		static class Accepter implements Runnable {
			private SSLSocket socket;

			public Accepter(SSLSocket socket) {
				this.socket = socket;
			}

			public void service() {
				Thread thread = new Thread(this);
				thread.start();
			}

			@Override
			public void run() {
				try {
					InputStream inputStream = socket.getInputStream();

					InputStreamReader inputstreamreader = new InputStreamReader(
							inputStream);
					BufferedReader bufferedreader = new BufferedReader(
							inputstreamreader);

					String string = null;
					while ((string = bufferedreader.readLine()) != null) {
						System.out.println(string);
						System.out.flush();
					}
				} catch (Exception e) {
					// replace with other code
					e.printStackTrace();
				}
			}
		}
	}


Client代码

建立连接,并发一个消息给Server。很简单。记得换行符以及调用flush方法。


public class SslClient {
		public static void main(String[] args) throws Exception {
			System.setProperty("javax.net.debug", "ssl,handshake");

			System.setProperty("javax.net.ssl.keyStore", "./cfg/client.jks");
			System.setProperty("javax.net.ssl.keyStorePassword", "123456");
			System.setProperty("javax.net.ssl.trustStore", "./cfg/servertrust.jks");
			System.setProperty("javax.net.ssl.trustStorePassword", "123456");

			SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory
					.getDefault();
			SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
					"127.0.0.1", 9100);

			OutputStream outputStream = sslsocket.getOutputStream();
			BufferedWriter bufferedWriter = new BufferedWriter(
					new OutputStreamWriter(outputStream));
			bufferedWriter.write("沉睡的雄狮\n");
			bufferedWriter.flush();

			TimeUnit.SECONDS.sleep(2000);
		}
	}


结束语

JDK后来加了SSLEngine这个类,具有异步通讯的能力。不过看官方文档,给出的代码很长。还是那句话,有条件的推荐用Netty或者Mina来处理通讯的问题,应该会比自己写的性能好一些。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。