上一篇《OpenSSL与KeyStore指令小集》里面说到,最近研究SSL加密,会给出一个Java的小示例。复制一份可以运行的代码到生产上是非常不负责任的行为,不过小示例可以带我们入门,快速看清事物的本质。罗马不是一天建成的。
本文将给出一个Java SSL Socket的小例子,包括了Server和Client。希望大家上手之后,要多去研究相关的资料,理解基础概念。Java的优点是封装得比较彻底,需要介入的地方比较少,缺点是随着Java版本的升级和发展,会有很多新的概念和类涌出来,都要搞清楚要费不少力,另外代码量也比较大(生产级别的代码)。
从最简单来说,Java里面只需要配置几个系统属性,创建及调用几个SSL相关的对象即可。这四个属性分别是:
KeyStore类型默认是JKS类型的,不是的话,还需要设置 javax.net.ssl.keyStoreType和javax.net.ssl.trustStoreType。
每一次收新的连接,都新开一个线程接待。生产上请用线程池等技术。更推荐用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();
}
}
}
}建立连接,并发一个消息给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来处理通讯的问题,应该会比自己写的性能好一些。
原文地址:http://blog.csdn.net/kimylrong/article/details/43603815