SSLServerSocket、SSLSocket简单例子

系统环境:

java version "1.8.0_66"  x64


一:使用keytool生成服务端证书

生成密钥对

keytool -genkeypair -alias myserver -keystore myserver.jks

输入密码123456(注意,两次输入的密码一样)

从密钥对中导出证书

keytool -exportcert -alias myserver -keystore myserver.jks -file trust.cer

把导出的证书导入到受信任的证书库中

keytool -importcert -file trust.cer -keystore trust.jks

输入密码123456(注意,两次输入的密码一样)


这样,就得到了2个jks证书文件


二:服务端代码

package com.lala.ssl;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
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.SSLServerSocketFactory;

import org.apache.commons.io.IOUtils;

public class SSLServer
{
	public static final int port = 4488;
	
	static SSLServerSocket createServerSocket(int port)throws Exception
	{
		KeyStore ks = KeyStore.getInstance("jks");
		InputStream input = new FileInputStream("d:/tmp/myserver.jks");
		ks.load(input, "123456".toCharArray());
		
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(ks, "123456".toCharArray());
		
		SSLContext context = SSLContext.getInstance("TLSv1.2");
		
		/**
		 * KeyManager[] 第一个参数是授权的密钥管理器,用来授权验证。TrustManager[]第二个是被授权的证书管理器,
		 * 用来验证服务器端的证书。第三个参数是一个随机数值,可以填写null。如果只是服务器传输数据给客户端来验证,就传入第一个参数就可以,
		 * 客户端构建环境就传入第二个参数。双向认证的话,就同时使用两个管理器。
		 */
		context.init(kmf.getKeyManagers(), null, null);
		
		input.close();
		
		SSLServerSocketFactory ssf = context.getServerSocketFactory();
		return (SSLServerSocket)ssf.createServerSocket(port);
	}
	public static void main(String[] args)throws Exception
	{
		final ServerSocket ss = createServerSocket(port);
		System.out.println("ssl server startup at port " + port);
		while(true)
		{
			final Socket s = ss.accept();
			new Thread(()-> {
				OutputStream output = null;
				try
				{
					output = s.getOutputStream();
					output.write("hello word".getBytes());
					output.flush();
				}catch(Exception e)
				{
					e.printStackTrace();
				}
				finally
				{
					IOUtils.closeQuietly(output);
					IOUtils.closeQuietly(s);
				}
			}).start();
		}
	}
}


三:客户端代码

package com.lala.ssl;

import java.io.FileInputStream;
import java.io.InputStream;
import java.net.Socket;
import java.security.KeyStore;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;

import org.apache.commons.io.IOUtils;

public class SSLClient
{
	static SSLSocket createSocket(String host, int port)throws Exception
	{
		KeyStore ks = KeyStore.getInstance("jks");
		InputStream input = new FileInputStream("d:/tmp/trust.jks");
		ks.load(input, "123456".toCharArray());
		
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
		tmf.init(ks);
		
		SSLContext context = SSLContext.getInstance("TLSv1.2");
		
		/**
		 * KeyManager[] 第一个参数是授权的密钥管理器,用来授权验证。TrustManager[]第二个是被授权的证书管理器,
		 * 用来验证服务器端的证书。第三个参数是一个随机数值,可以填写null。如果只是服务器传输数据给客户端来验证,就传入第一个参数就可以,
		 * 客户端构建环境就传入第二个参数。双向认证的话,就同时使用两个管理器。
		 */
		context.init(null, tmf.getTrustManagers(), null);
		
		input.close();
		
		SocketFactory sf = context.getSocketFactory();
		return (SSLSocket)sf.createSocket(host, port);
	}
	
	public static void main(String[] args) throws Exception
	{
		Socket s = createSocket("127.0.0.1", SSLServer.port);
		InputStream input = s.getInputStream();
		String response = IOUtils.toString(input);
		System.out.println(response);
		IOUtils.closeQuietly(input);
		IOUtils.closeQuietly(s);
	}
}


这里,服务端演示的是,服务端给连接上的客户端发送hello word消息,客户端收到之后,输出。

先启动服务端,然后启动客户端,即可看到输出

你可能感兴趣的:(ssl)