【问题标题】:Java SSL Socket ProgrammingJava SSL 套接字编程
【发布时间】:2014-08-17 00:51:16
【问题描述】:

当我已经完成了一个使用普通 ServerSocket 的 Java 聊天程序时,我读到了 SSLSocket。 我正在尝试用 SSlSocket 替换普通的 ServerSocket,互联网上没有太多内容,但我发现了一些东西。 现在我的 WhServer 类看起来像这样: 此类是在选定端口中启动 Socket 的类,如果您需要查看其他类,我将编辑问题:

import java.io.IOException;
import java.net.*;
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class WhServer extends Thread {

  private int port;
  private ServerSocket server;
  private ChannelsManager manager;
  SSLContext context;
  SSLSocketFactory sslSf;

  public WhServer(int port, ChannelsManager manager) throws IOException {
    this.port = port;
    this.manager = manager;     
  }

  public void ServerStop() throws IOException{
      server.close();      
  }

  public WhServer(int port) throws IOException {
    this(port, new ChannelsManager());
  }

  public int getPort() {
    return port;
  }

  public void run() {
    try {
      while(true) {     
        ServerSocketFactory ssf = ServerSocketFactory.getDefault();
        server = ssf.createServerSocket(port);      
        Socket socket = server.accept();        
        sslSf = context.getSocketFactory();
        SSLSocket sslSocket = (SSLSocket) sslSf.createSocket(socket, null,socket.getPort(), false);
        sslSocket.setUseClientMode(false);      
        manager.initialite(socket);
      }
    } catch(Exception ex) {
        ex.printStackTrace();
    }
  }

}

【问题讨论】:

  • 看起来你的 SSLContext 还没有初始化,它只能为空(除非在这个类之外初始化)
  • 不,不是。我的错误,但我该如何初始化它?我需要什么参数?我是套接字的初学者,所以如果你能给我看一个小代码示例,那将是完美的。 (SSLContextSpi, Provider, String) 这些参数是什么意思?
  • 恐怕这不是我有任何经验的领域,但快速浏览 API 文档会发现一些静态 getInstance() 方法:docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLContext.html
  • 所以我不需要那样初始化它?这是我采用的示例代码 (stackoverflow.com/questions/6559859/…)
  • 互联网上关于这个的内容不多?摆脱它。 SO 和 Oracle Java 论坛充满了这方面的信息。

标签: java sockets ssl


【解决方案1】:

首先,您的SSLContext context 实例变量永远不会被初始化,所以它是null。这里没有特定于 SSL 或套接字的内容,它只是一个基本的 Java 错误:如果您尝试对此调用任何内容,它将引发 NPE。

其次,即使它不为空(例如,您可以使用context = SSLContext.getInstance("TLS") 创建一个新实例,请参阅SSLContext section of the Java Cryptography Architecture Standard Algorithm Name Documentation,如SSLContext API 文档中所述),您仍然需要通过以下方式初始化SSLContext它的init method

由于您尝试实现服务器,因此您需要提供非空密钥管理器,否则您将收到 SSLHandshakeException 提示“没有共同的密码套件”。例如,您可以在 this answer 中找到有关此内容的详细信息。

另外,你不需要像你一样使用普通的Sockets 并在接受后将它们升级为SSLSockets。这不一定是错误的,但以下可能更容易:

 // Assuming you've initialised your SSLContext
  SSLServerSocketFactory sslSf = context.getServerSocketFactory();
  SSLServerSocket server = (SSLServerSocket) sslSf.createServerSocket(port);
  SSLServerSocketFactory ssf = ServerSocketFactory.getDefault();
  server = ssf.createServerSocket(port);      
  SSLSocket socket = (SSLSocket)server.accept();

来自 SSLServerSocketFactory 的套接字已经处于服务器模式。 当然,工厂一般不需要在while 循环内。

【讨论】:

  • 这有助于我理解更多谢谢。只有一件事什么是密钥管理器?在他使用远程密钥管理器的链接答案中,还有其他方法可以实现密钥管理器吗?
  • 您应该关注this other answer的答案中的链接。
  • 我读到Java有一个默认的密钥库。如何在不需要外部文件的情况下使用它?
  • 有一个默认的信任库,没有默认的密钥库。
  • 对不起,我一直有问题。我需要他们都信任库和密钥库,不是吗?因为当我尝试通过 init 初始化上下文时,我需要这些参数(km、tm、随机)还是我错了?
【解决方案2】:

上下文为空。在您的代码中没有任何地方正在初始化它。

这里有一些静态方法可以用来初始化它。 http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLContext.html

静态 SSLContext getInstance(字符串协议) 返回实现指定安全套接字协议的 SSLContext 对象。

静态 SSLContext getInstance(String protocol, Provider provider) 返回实现指定安全套接字协议的 SSLContext 对象。

静态 SSLContext getInstance(字符串协议,字符串提供者) 返回实现指定安全套接字协议的 SSLContext 对象。

协议字符串的一些有效值是“SSL”、“SSLv2”、“SSLv3”...

因此,首先,如果您打算将该“上下文”变量保留为成员变量,请将其设为 final 并在构造函数中对其进行初始化,如下所示:

public WhServer(int port, ChannelsManager manager) throws IOException {
    this.port = port;
    this.manager = manager;
    try {
        context = SSLContext.getInstance("SSL"); //pick the SSL protocol you need.
    } catch (Throwable t) { t.printStackTrace(); }

}

【讨论】:

【解决方案3】:

首先您需要使用以下代码创建 SSLContext:

  KeyStore keyStore = KeyStore.getInstance("JKS");
  keyStore.load(new FileInputStream("test.jks"),"passphrase".toCharArray());

  // Create key manager
  KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
  keyManagerFactory.init(keyStore, "passphrase".toCharArray());
  KeyManager[] km = keyManagerFactory.getKeyManagers();

  // Create trust manager
  TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
  trustManagerFactory.init(keyStore);
  TrustManager[] tm = trustManagerFactory.getTrustManagers();

  // Initialize SSLContext
  SSLContext sslContext = SSLContext.getInstance("TLSv1");
  sslContext.init(km,  tm, null);

将 test.jks 替换为您自己的密钥库位置。

要了解Java中的SSL通信模型,可以参考Java Secure Socket Extension (JSSE) Reference Guide

A HTTPS client and HTTPS server demo in Java 提供了一个关于如何在 Java 中创建 SSL 客户端和 SSL 服务器的相当演示。

【讨论】:

    猜你喜欢
    • 2013-10-09
    • 1970-01-01
    • 2011-10-10
    • 2011-08-29
    • 2015-05-21
    • 1970-01-01
    • 2011-04-26
    相关资源
    最近更新 更多