セキュアサーバーとセキュリティクライアントのSSLに基づくパラダイムを作成します。

セキュアサーバーとセキュリティクライアントのSSLに基づくパラダイムを作成します。

第15章以下参照Sunweiqinは本を「Javaのネットワークプログラミングのコア技術が説明」を書きました。
ソースコードのダウンロードアドレスは次のとおりです。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();}
    }
  }
}

SSLSocketFactoryオブジェクトを作成するには、上記のEchoClientクラス、およびそれがの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コマンドラインディレクトリの第15章の例に移動し、次の手順EchoServerとEchoClientを実行します。
(1)は、クラスパスを設定し、コマンドを実行します。「セットクラスパス= Cを:\第15章 \クラス」。
(2)ファイル名を指定して実行は、EchoServerサーバを起動するコマンド"javaのEchoServerを開始します"。
(3)ファイル名を指定して実行"のjava EchoClient"コマンドがEchoClientの顧客を開始します。

おすすめ

転載: blog.51cto.com/sunweiqin/2452135