Create a paradigm based on a secure server and security client's SSL

Create a paradigm based on a secure server and security client's SSL

Chapter 15 the following reference Sunweiqin wrote "Java Network Programming core technology explain" a book.
Source code download address is: http://lesson.javathinker.net/javanet/javanetsourcecode.rar

The following EchoServer class creates an SSL-based secure server, it is in server mode.

/* 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 create a class above SSLContext object, then the object is created by the SSLServerSocketFactory it, and then create SSLServerSocket objects from this factory object. For the following program code:

System.out.println(serverSocket.getUseClientMode()?
               "客户模式":"服务器模式");
System.out.println(serverSocket.getNeedClientAuth()?
               "需要验证对方身份":"不需要需要验证对方身份");

Print results:

服务器模式
不需要验证对方身份

Thus, by default, SSLServerSocket in server mode, must prove their identity to each other, but do not need to verify each other's identity, which does not require the production of a security certificate.

If you want to output log information underlying the program is running JSSE implementation, you can put "javax.net.debug" system property is set to "all":
System.setProperty("javax.net.debug", "all");

The following EchoClient class creates a client-based SSL security, which is in client mode.

/* 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();}
    }
  }
}

Above EchoClient class to create a SSLSocketFactory object, and then it creates a SSLSocket object. For the following program code:

System.out.println(socket.getUseClientMode()?
                    "客户模式":"服务器模式");

Print results:

客户模式

Thus, by default, SSLSocket objects created by SSLSocketFactory in client mode, the other party does not have to confirm their identity.
EchoClient class rely TrustManager to decide whether to trust the security certificate EchoServer presented. SSLSocketFactory objects EchoClient class by SSLContext object to create. This SSLContext object by TrustManager to manage the security certificate trust. In this case, the security certificate TrustManager trusted located test.keystore key store file.

In this case, the server is located test.keystore key store file to the security certificate presented by the client. In practice, the key store file server contains the key pair from a security perspective, the client trusted key store file should contain only the public key, so the server and client libraries should use different keys file.

Assumes that the file with EchoServer.class and EchoClient.class file in the same directory. Go to the directory chapter15 example where the DOS command line, run the following steps EchoServer and EchoClient:
(1) set the classpath, run the command "set classpath = C: \ chapter15 \ classes".
(2) Run "start java EchoServer" command to start EchoServer server.
(3) Run "java EchoClient" command to start EchoClient customers.

Guess you like

Origin blog.51cto.com/sunweiqin/2452135