보안 서버 및 보안 클라이언트의 SSL 기반의 패러다임을 만들기
제 15 장 Sunweiqin 쓴 다음 참조는 책을 "자바 네트워크 프로그래밍 핵심 기술 설명".
소스 코드 다운로드 주소는 다음과 같습니다 http://lesson.javathinker.net/javanet/javanetsourcecode.rar
다음 EchoServer 클래스는 SSL 기반 보안 서버를 생성, 그것은 서버 모드에 있습니다.
/* EchoServer.java */
import java.net.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
public class EchoServer {
private int port=8000;
private SSLServerSocket serverSocket;
public EchoServer() throws Exception {
//输出跟踪日志
//System.setProperty("javax.net.debug", "all");
SSLContext context=createSSLContext();
SSLServerSocketFactory factory=context.getServerSocketFactory();
serverSocket =(SSLServerSocket)factory.createServerSocket(port);
System.out.println("服务器启动");
System.out.println(
serverSocket.getUseClientMode()? "客户模式":"服务器模式");
System.out.println(serverSocket.getNeedClientAuth()?
"需要验证对方身份":"不需要验证对方身份");
String[] supported=serverSocket.getSupportedCipherSuites();
serverSocket.setEnabledCipherSuites(supported);
}
public SSLContext createSSLContext() throws Exception {
//服务器用于证实自己身份的安全证书所在的密钥库
String keyStoreFile = "test.keystore";
String passphrase = "123456";
KeyStore ks = KeyStore.getInstance("JKS");
char[] password = passphrase.toCharArray();
ks.load(new FileInputStream(keyStoreFile), password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), null, null);
//当要求客户端提供安全证书时,服务器端可创建TrustManagerFactory,
//并由它创建TrustManager,TrustManger根据与之关联的KeyStore中的信息,
//来决定是否相信客户提供的安全证书。
//客户端用于证实自己身份的安全证书所在的密钥库
//String trustStoreFile = "test.keystore";
//KeyStore ts = KeyStore.getInstance("JKS");
//ts.load(new FileInputStream(trustStoreFile), password);
//TrustManagerFactory tmf =
// TrustManagerFactory.getInstance("SunX509");
//tmf.init(ts);
//sslContext.init(kmf.getKeyManagers(),
// tmf.getTrustManagers(), null);
return sslContext;
}
public String echo(String msg) {
return "echo:" + msg;
}
private PrintWriter getWriter(Socket socket)throws IOException{
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}
private BufferedReader getReader(Socket socket)throws IOException{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public void service() {
while (true) {
Socket socket=null;
try {
socket = serverSocket.accept(); //等待客户连接
System.out.println("New connection accepted "
+socket.getInetAddress()
+ ":" +socket.getPort());
BufferedReader br =getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
pw.println(echo(msg));
if (msg.equals("bye")) //如果客户发送的消息为“bye”,就结束通信
break;
}
}catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(socket!=null)socket.close(); //断开连接
}catch (IOException e) {e.printStackTrace();}
}
}
}
public static void main(String args[])throws Exception {
new EchoServer().service();
}
}
EchoServer 다음 개체가 SSLServerSocketFactory 그것에 의해 생성 SSLContext 객체 위의 클래스를 만든 다음 SSLServerSocket에이 공장 개체에서 개체를 만들 수 있습니다. 다음 프로그램 코드의 경우 :
System.out.println(serverSocket.getUseClientMode()?
"客户模式":"服务器模式");
System.out.println(serverSocket.getNeedClientAuth()?
"需要验证对方身份":"不需要需要验证对方身份");
결과를 인쇄 :
服务器模式
不需要验证对方身份
따라서, 기본적으로 SSLServerSocket에 서버 모드에서 서로 자신의 신분을 증명해야하지만, 보안 인증서의 생산을 필요로하지 않는 서로의 신분을 확인 할 필요가 없습니다.
당신이 JSSE 구현을 실행중인 프로그램을 기본이되는 출력 로그 정보를 원하는 경우, 당신은 넣을 수 있습니다 "javax.net.debug의"시스템 프로퍼티가 설정되어있는 "모든"System.setProperty("javax.net.debug", "all");
다음 EchoClient 클래스는 클라이언트 모드에있는 클라이언트 기반 SSL 보안을 만듭니다.
/* EchoClient.java */
import java.net.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
public class EchoClient {
private String host="localhost";
private int port=8000;
private SSLSocket socket;
public EchoClient()throws IOException{
SSLContext context=createSSLContext();
SSLSocketFactory factory=context.getSocketFactory();
socket=(SSLSocket)factory.createSocket(host,port);
String[] supported=socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(supported);
System.out.println(socket.getUseClientMode()?
"客户模式":"服务器模式");
}
public SSLContext createSSLContext() throws Exception {
String passphrase = "123456";
char[] password = passphrase.toCharArray();
//设置客户端所信任的安全证书所在的密钥库
String trustStoreFile = "test.keystore";
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(new FileInputStream(trustStoreFile), password);
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null,tmf.getTrustManagers(), null);
return sslContext;
}
public static void main(String args[])throws IOException{
new EchoClient().talk();
}
private PrintWriter getWriter(Socket socket)throws IOException{
OutputStream socketOut = socket.getOutputStream();
return new PrintWriter(socketOut,true);
}
private BufferedReader getReader(Socket socket)throws IOException{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public void talk()throws IOException {
try{
BufferedReader br=getReader(socket);
PrintWriter pw=getWriter(socket);
BufferedReader localReader=
new BufferedReader(new InputStreamReader(System.in));
String msg=null;
while((msg=localReader.readLine())!=null){
pw.println(msg);
System.out.println(br.readLine());
if(msg.equals("bye"))
break;
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{socket.close();}catch(IOException e){e.printStackTrace();}
}
}
}
위 EchoClient 클래스는 SSLSocketFactory의 객체를 생성하고, 다음은 SSLSocket에 개체를 만듭니다. 다음 프로그램 코드의 경우 :
System.out.println(socket.getUseClientMode()?
"客户模式":"服务器模式");
결과를 인쇄 :
客户模式
따라서, 기본적으로, SSLSocket과는 클라이언트 모드에서의 SSLSocketFactory에 의해 생성 된 오브젝트, 상대방은 자신의 정체성을 확인 할 필요가 없습니다.
EchoClient 클래스 EchoServer가 제시 한 보안 인증서를 신뢰 여부를 결정할의 TrustManager를 의존하고 있습니다. SSLSocketFactory를 생성하는 SSLContext 객체로 EchoClient 클래스를 객체. 의 TrustManager의이 SSLContext 객체는 보안 인증서 신뢰를 관리 할 수 있습니다. 이 경우, 보안 인증서의 TrustManager은 test.keystore 키 저장소 파일을 위치 믿었습니다.
이 경우, 서버는 클라이언트가 제시 한 보안 인증서에 test.keystore 키 저장소 파일에 있습니다. 실제로, 키 저장소 파일 서버 보안의 관점에서 키 쌍을 포함하는 서버와 클라이언트 라이브러리가 서로 다른 키를 사용해야하므로, 클라이언트는 만 공개 키를 포함해야 키 저장소 파일을 신뢰할 파일.
같은 디렉토리에 EchoServer.class 및 EchoClient.class 파일로 파일이 있다고 가정합니다. : DOS 명령 줄, 다음을 실행이 EchoServer 및 EchoClient 단계 디렉토리 15 장 예제로 이동
명령 "설정 클래스 경로 = C를 : \ 15 장 실행 (1) 클래스 패스를 설정 \ 클래스를".
(2) 실행 EchoServer 서버를 시작하는 명령 "자바 EchoServer를 시작합니다."
(3) 실행 "자바 EchoClient"명령 EchoClient 고객을 시작합니다.