2014-06-26 3 views
-1

Я прочитал о SSLSocket, когда я уже закончил программу чата с java, которая использует обычный ServerSocket. Я пытаюсь заменить обычный ServerSocket на SSlSocket, в Интернете мало чего, но я что-то нашел. Теперь мой класс WhServer выглядеть следующим образом: Этот класс является тот, который начать гнездо в выбранном порту, если вам нужно, чтобы увидеть другие классы я буду редактировать вопрос:Java SSL Socket Programming

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

} 
+0

Похоже, что вы не инициализировали свой SSLContext, он может быть только нулевым (если не инициализирован вне этого класса) – NickJ

+0

Нет, это не так. Моя ошибка, но как я могу ее инициализировать? Какие параметры мне нужны? Я новичок с сокетами, поэтому, если вы можете показать мне пример небольшого кода, это было бы прекрасно. (SSLContextSpi, Provider, String), что означает каждый из этих параметров? –

+0

Я боюсь, что это не та область, с которой я сталкиваюсь, но быстрый взгляд на документы API показывает некоторые статические методы getInstance(): http://docs.oracle.com/javase/7/docs/api/ javax/net/ssl/SSLContext.html – NickJ

ответ

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, например.

Кроме того, вам не нужно использовать простой Socket s и обновить их до SSLSocket s после принятия, как вы. Это не обязательно плохо, но следующий может быть проще:

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

+0

Это помогло мне больше узнать спасибо. Только одно, что такое keymanager? В связанном ответе он использует удаленный keymanager, есть другой способ реализовать keymanager? –

+0

Вы должны следить за ссылкой в ​​этом ответе на [этот другой ответ] (http://stackoverflow.com/a/6341566/372643). – Bruno

+0

Я читал, что у Java есть хранилище ключей по умолчанию. Как использовать его без необходимости использования внешних файлов? –

1

контекст является недействительным. нигде в вашем коде он не инициализируется.

Вот несколько статических методов, которые вы можете использовать для его инициализации. http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLContext.html

статического SSLContext деЫпзЬапс (протокол String) Возвращает объект SSLContext, который реализует указанный защищенный протокол сокета.

статического SSLContext деЫпзЬапса (String протокол, провайдер провайдер) Возвращает объект SSLContext, который реализует указанный защищенный протокол сокета.

статическая SSLContext деЫпзЬапса (строка протокол, поставщик Строки) Возвращает объект SSLContext, который реализует указанный защищенный протокол сокета.

Некоторые допустимые значения для строки протокола являются «SSL», «SSLv2», «SSLv3» ...

Итак, в первую очередь, если вы собираетесь держать, что «контекст» переменную в качестве переменной-члена , сделать его окончательным и инициализировать его в конструкторе, как это:

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

} 
0

Прежде всего, необходимо создать 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 с собственным адресом хранилища ключей.

Чтобы понять модель связи SSL на Java, вы можете обратиться к Java Secure Socket Extension (JSSE) Reference Guide.

A HTTPS client and HTTPS server demo in Java содержит довольно подробную информацию о том, как создать SSL-клиент и SSL-сервер в Java.