1

我正在尝试使用 Twitter4J 从 Twitter 流 API 中检索推文。该项目使用 SSLSocket 连接到远程服务器以检索一些数据,然后调用 Twitter4J。问题是,如果我建立这个连接 Twitter4J 会出现这个异常:

[2013 年 2 月 20 日星期三 11:32:02 CET]sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径

如果我不建立连接并清理下一行定义的密钥库,则不会发生这种情况:

System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");

连接代码是这样的:

private String publishFetcher() throws UnknownHostException, IOException {
    // Set trustStore.
    System.setProperty("javax.net.ssl.trustStore", properties.getProperty("trustedStore"));
    System.setProperty("javax.net.ssl.trustStorePassword", properties.getProperty("trustedStorePassword"));

    String host = properties.getProperty("host");
    int hostPort = Integer.parseInt(properties.getProperty("host_port"));
    SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    SSLSocket socket = (SSLSocket) factory.createSocket(host, hostPort);

    // Get input and output streams from socket connection.
    BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter output = new PrintWriter(socket.getOutputStream());

    // Request connection token to controller
    String connectionToken = getConnectionToken(input, output);

    // Publish fetcher
    final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
    TwitterFetcher fetcher = new TwitterFetcher(connector);
    Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
    Registry registry = LocateRegistry.createRegistry(rmiPort);
    registry.rebind(connectionToken, stub);

    // Send RMI port
    output.write(String.valueOf(rmiPort) + "\n");
    output.flush();

    input.close();
    output.close();

    // Clean trusteStore properties.
    System.clearProperty("javax.net.ssl.trustStore");
    System.clearProperty("javax.net.ssl.trustStorePassword");

    return connectionToken;
}

我认为这个问题与 SSLSocketFactory 有关,因为我在不同的项目中测试了一些东西。例如,这段代码就像一个魅力:

SSLSocketFactory deffactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();

factory = deffactory;
// Twitter4J code...

但是这段代码不起作用:

System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
// Twitter4J code...

我不能在我的实际项目中做同样的事情,因为休息......几乎所有东西^^

可能是什么问题呢?和解决方案?

4

1 回答 1

1

代码的问题是我正在替换信任库,而不是为我的应用程序创建一个新的。解决问题的代码是下一个:

private SSLSocket getSSLSocket() throws TrackerSSLConnectionException {
    try {
        // Load properties.
        String keystore = properties.getProperty("keystore");
        String passphrase = properties.getProperty("keystorePassphrase");
        String host = properties.getProperty("host");
        int hostPort = Integer.parseInt(properties.getProperty("host_port"));

        // Create keystore.
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(keystore), passphrase.toCharArray());

        // Get factory for the given keystore.
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(null, tmf.getTrustManagers(), null);
        SSLSocketFactory factory = ctx.getSocketFactory();

        return (SSLSocket) factory.createSocket(host, hostPort);
    } catch (Exception e) {
        throw new TrackerSSLConnectionException(e.getMessage(), e.getCause());
    }
}

private String publishFetcher() throws TrackerSSLConnectionException, IOException {
    // Get socket connection.
    SSLSocket socket = getSSLSocket();

    // Get input and output streams from socket.
    BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter output = new PrintWriter(socket.getOutputStream());

    // Request connection token to controller.
    String connectionToken = getConnectionToken(input, output);

    // Publish fetcher.
    final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
    TwitterFetcher fetcher = new TwitterFetcher(connector);
    Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
    Registry registry = LocateRegistry.createRegistry(rmiPort);
    registry.rebind(connectionToken, stub);

    // Send RMI port.
    output.write(String.valueOf(rmiPort) + "\n");
    output.flush();

    input.close();
    output.close();

    return connectionToken;
}
于 2013-02-21T10:02:21.730 回答