Вопрос

I'm trying to retrieve tweets from the Twitter streaming API using Twitter4J. The project connects to a remote server using an SSLSocket to retrieve some data and, after this, the Twitter4J is called. The problem is that if I establish this connection the Twitter4J arise this exception:

[Wed Feb 20 11:32:02 CET 2013]sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

This doesn't happen if I don't make the connection and I clean the keystore defined with the next lines:

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

The code to connect is this one:

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;
}

I think that the problem is related with SSLSocketFactory because I tested somethings in a different project. For example, this code works like a charm:

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...

But this code doesn't work:

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

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

I can't do the same in my real project because breaks... almost everything ^^

What could be the problem? and the solution?

Это было полезно?

Решение

The problem with the code is that I was replacing the trust store instead of creating a new one for my app. The code that solves the problems is the next one:

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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top