博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用JSSE实现网络安全通信
阅读量:4155 次
发布时间:2019-05-26

本文共 7855 字,大约阅读时间需要 26 分钟。

    在网络上信息由源主机到目标主机要经过很多路由和计算机,通常这些机器不会监听路过的信息。但在使用网络银行进行网上消费时,不加以保护的账号密码很有可能被黑客截获并利用给消费者造成不可估量的损失。

      Java安全套接字扩展(JSSE,Java Secure Socket Extension)为基于SSL和TLS协议的Java网络应用程序提供了Java API及参考实现。JSSE支持数据加密、服务器端身份验证、数据完整性。使用JSSE,能保证采用各种应用层协议(HTTP、Telnet、FTP等)的客户程序与服务器程序安全地交换数据

     要实现用JSSE交换数据,需要用到证书,获取证书有两种方式,一是从权威机构购买证书,二是创建自我签名的证书。我们用JDK现有的工具keytool创建一个自我签名的证书。

 

服务端证书

 

客户端证书

 

jks文件是一个密钥容器,证书都会存储在里面,如果要导出刚刚生成的证书,用下面的命令

keytool -export -alias keyAlias-storepass changeit -file server.cer -keystore keystore.jks

JSSE中负责安全通信的核心类是SSLServerSocket类和SSLSocket类,它们分别是ServerSocket与Socket类的子类。SSLSocket对象由SSLSocketFactory创建,不过SSLServerSocket的accept()方法也会创建SSLSocket。SSLServerSocketFactory、SSLSocketFactory对象都由SSLContext对象创建。

 

下面是一个简单的例子,客户端和服务端采用刚才生成的两个证书进行通信,在控制台随便输入信息,服务端都会响应,输入"88"结束本次会话。

 

客户端:

package com.bill99.seashell.domain;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManagerFactory;public class MySSLClient {		private static final String SSL_TYPE = "SSL";	private static final String X509 = "SunX509";	private static final String KS_TYPE = "JKS";		private SSLSocket sslcntSocket;		public MySSLClient(String targetHost,int port) throws Exception {		SSLContext sslContext = createSSLContext(); //创建SSL上下文		SSLSocketFactory sslcntFactory =(SSLSocketFactory) sslContext.getSocketFactory();		sslcntSocket = (SSLSocket) sslcntFactory.createSocket(targetHost, port);		String[] supported = sslcntSocket.getSupportedCipherSuites();		sslcntSocket.setEnabledCipherSuites(supported); //设置加密套件	}		private SSLContext createSSLContext() throws Exception{		KeyManagerFactory kmf = KeyManagerFactory.getInstance(X509);		TrustManagerFactory tmf = TrustManagerFactory.getInstance(X509);		//-----------------------------------------------------------		String clientKeyStoreFile = "c:\\merchant.jks"; //客户端用于证实自己身份的证书		String cntPassphrase = "baitour";               //证书密码		char[] cntPassword = cntPassphrase.toCharArray();		KeyStore clientKeyStore = KeyStore.getInstance(KS_TYPE);		clientKeyStore.load(new FileInputStream(clientKeyStoreFile),cntPassword);		//-----------------------------------------------------------		String serverKeyStoreFile = "c:\\paygateway.jks"; //服务端证书		String svrPassphrase = "99bill";                 //证书密码		char[] svrPassword = svrPassphrase.toCharArray();		KeyStore serverKeyStore = KeyStore.getInstance(KS_TYPE);		serverKeyStore.load(new FileInputStream(serverKeyStoreFile), svrPassword);				kmf.init(clientKeyStore, cntPassword); 				tmf.init(serverKeyStore);  //添加信任的证书				SSLContext sslContext  = SSLContext.getInstance(SSL_TYPE);		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);				return sslContext;	}		/**	 * 发送消息至服务器	 * @param sayMsg 发送给服务器信息	 * @return String 服务器响应的信息	 * @throws IOException 发送过程Socket出错时抛出此异常	 */	public String sayToSvr(String sayMsg) throws IOException{		BufferedReader ioReader = new BufferedReader(new InputStreamReader(				sslcntSocket.getInputStream()));		PrintWriter ioWriter = new PrintWriter(sslcntSocket.getOutputStream());		ioWriter.println(sayMsg);		ioWriter.flush();		return ioReader.readLine();	}		public static void main(String[] args) throws Exception {		MySSLClient mysslCnt = new MySSLClient("127.0.0.1",7612);		BufferedReader ioReader = new BufferedReader(new InputStreamReader(System.in));		String sayMsg = "";		String svrRespMsg= "";		while( (sayMsg = ioReader.readLine())!= null ) {			svrRespMsg = mysslCnt.sayToSvr(sayMsg);			if(svrRespMsg != null && !svrRespMsg.trim().equals("")) {				System.err.println("服务器响应:"+svrRespMsg);			}			if(sayMsg.trim().equals("88")) {				break ;			}		}	}}

 服务端

package com.bill99.seashell.domain;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;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 javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManagerFactory;public class MySSLServer {	private static final String SSL_TYPE = "SSL";	private static final String KS_TYPE = "JKS";	private static final String X509 = "SunX509";		private final static int PORT = 7612;  //监听端口	private final static Object lock = new Object();//对象锁		private static MySSLServer mysslServer;		private SSLServerSocket svrSocket;		/**	 * 通过单态模式获得MySSLServer对象	 */	public static MySSLServer getInstance() throws Exception {		synchronized (lock) {			if (mysslServer == null) {				mysslServer = new MySSLServer();			}			return mysslServer;		}	}		private MySSLServer() throws Exception{		//输出跟踪日志		System.setProperty("javax.net.debug","all");		//创建SSL上下文		SSLContext sslContext = createSSLContext();				SSLServerSocketFactory serverFactory = sslContext.getServerSocketFactory();		svrSocket =(SSLServerSocket) serverFactory.createServerSocket(PORT);		svrSocket.setNeedClientAuth(true);  //需要验证客户的身份				System.err.println("【SSL服务器启动,监听端口:"+PORT+ "】");		System.err.println(svrSocket.getNeedClientAuth() ? "【需要验证对方身份】" : "【不需要验证对方的身份】");		//设置支持加密的套件		String[] supported = svrSocket.getEnabledCipherSuites();		svrSocket.setEnabledCipherSuites(supported);	}		/**	 * 创建上下文	 * @return SSLContext	 * @throws Exception 在创建SSLContext发生错误时抛出此异常	 */	private SSLContext createSSLContext() throws Exception{		//证书管理器		KeyManagerFactory kmf = KeyManagerFactory.getInstance(X509);		//信任管理器		TrustManagerFactory tmf = TrustManagerFactory.getInstance(X509);				//服务器证书加载到证书管理器		//----------------------------------------------------------		String serverKeyStoreFile = "c:\\paygateway.jks"; //服务器用于证实自己身份的证书		String svrPassphrase = "99bill";               //服务器证书密码		char[] svrPassword = svrPassphrase.toCharArray();		KeyStore serverKeyStore = KeyStore.getInstance(KS_TYPE);		serverKeyStore.load(new FileInputStream(serverKeyStoreFile), svrPassword);		kmf.init(serverKeyStore, svrPassword);		//客户机证书加载到证书管理器		//-----------------------------------------------------------		String clientKeyStoreFile = "c:\\merchant.jks"; //客户端用于证实自己身份的证书		String cntPassphrase = "baitour";               //证书密码		char[] cntPassword = cntPassphrase.toCharArray();		KeyStore clientKeyStore = KeyStore.getInstance(KS_TYPE);		clientKeyStore.load(new FileInputStream(clientKeyStoreFile),cntPassword);		tmf.init(clientKeyStore);  //添加信任的证书				SSLContext sslContext  = SSLContext.getInstance(SSL_TYPE);		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);				return sslContext;	}		/**	 * 开始服务	 */	public void startService() {		SSLSocket cntSocket = null;		BufferedReader ioReader = null;		PrintWriter ioWriter = null;		String tmpMsg = null;		while( true ) {			try {				cntSocket =(SSLSocket) svrSocket.accept();				System.err.println("[有客户机连接,IP:"+cntSocket.getInetAddress()+"]");				ioReader = new BufferedReader(new InputStreamReader(cntSocket.getInputStream()));				ioWriter = new PrintWriter(cntSocket.getOutputStream());								while ( (tmpMsg = ioReader.readLine()) != null) {					System.err.println("[客户机说:"+tmpMsg+"]");					if("88".equals(tmpMsg)) {						break;					}					tmpMsg = " **** Welcome to our website  **** ";					ioWriter.println(tmpMsg);					ioWriter.flush();					System.err.println("[服务器说:"+tmpMsg+"]");				}			} catch(IOException e) {				e.printStackTrace();			} finally {				try {					if(cntSocket != null) cntSocket.close();				} catch(Exception ex) {ex.printStackTrace();}			}		}//end while	}//end startService method		public static void main(String[] args) throws Exception {		MySSLServer mysslSvr = MySSLServer.getInstance();		mysslSvr.startService();	}}
 

转载地址:http://kjkxi.baihongyu.com/

你可能感兴趣的文章
patch补丁文件格式
查看>>
RK3399 ffmpeg编译
查看>>
jz2440 内核编译问题
查看>>
rk3399 内核编译报错
查看>>
编译驱动Makefile解析
查看>>
设备树jz2440开发环境镜像说明
查看>>
uboot-1-分析之编译体验
查看>>
rk3399源码,uboot,内核编译
查看>>
uboot-2,3分析之源码
查看>>
Linux-insmod/rmmod/lsmod驱动模块相关命令
查看>>
libfrelocation R_AARCH64_ADR_PREL_PG_HI21 against symbol which may bind externally can not be used
查看>>
芯片资料中的pad和pin的区别
查看>>
gzip bzip2 区别
查看>>
proc目录下的进程目录
查看>>
mount -a
查看>>
【Hi35**】制作根文件系统
查看>>
GV7704中文资料 hd-vlc
查看>>
arm中R0-R15寄存器的作用
查看>>
LCD基础概念
查看>>
嵌入式触摸屏
查看>>