SSL с гризли и Джерси

Я пытаюсь заставить гризли использовать шифрование SSL и по-прежнему нормально работать с Джерси. Я просмотрел весь Интернет и нашел всевозможные попытки использования SSL с помощью Grizzly и Jersey. Похоже, есть разные способы сделать это в зависимости от того, какую версию вы используете и как вы решили ее реализовать. Я еще не смог получить какие-либо примеры для работы с моим кодом.

Вот как я запускаю свой сервер:

static HttpServer startSecureServer() throws IOException{
        ResourceConfig rc=new PackagesResourceConfig("server.grizzlyresources");
        SSLContextConfigurator sslCon=new SSLContextConfigurator();

        sslCon.setKeyStoreFile(ConfigLoader.getKeystoreLocation()); // contains server keypair
        sslCon.setKeyStorePass(ConfigLoader.getKeystorePassword());

        System.out.println("Starting server on port "+ConfigLoader.getHttpsServerPort());
        HttpServer secure=GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED, rc);
        secure.stop();

        HashSet<NetworkListener> lists=new HashSet<NetworkListener>(secure.getListeners());
        for (NetworkListener listener : lists){
            listener.setSecure(true);
            SSLEngineConfigurator ssle=new SSLEngineConfigurator(sslCon);
            listener.setSSLEngineConfig(ssle);
            secure.addListener(listener);
            System.out.println(listener);
        }

        secure.start();
        return secure;
}

private static URI getBaseURISecured(){
    return UriBuilder.fromUri("https://0.0.0.0/").port(ConfigLoader.getHttpsServerPort()).build();
}

private static final URI BASE_URI_SECURED = getBaseURISecured();

ConfigLoader загружает информацию из файла конфигурации. Когда я запускаю этот код, он запускает сервер, находит ресурсы в пакете server.grizzlyresources и отлично работает! Кроме одного. Сервер не защищен. Я могу подключиться к нему по телнету и отправить HTTP-запрос в виде простого текста для одного из моих ресурсов, и он вернет его. Таким образом, код работает для запуска сервера, но вся его часть SSL просто обходится. Любые идеи, как это исправить или почему это может быть сделано?

Вот вывод в консоль при запуске:

Starting server on port 9999
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  server.grizzlyresources
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class server.grizzlyresources.SessionResource
  class server.grizzlyresources.LoginResource
Jan 13, 2014 9:51:08 AM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
Jan 13, 2014 9:51:08 AM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.12 02/15/2012 04:51 PM'
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:9999]
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener stop
INFO: Stopped listener bound to [0.0.0.0:9999]
NetworkListener{name='grizzly', host='0.0.0.0', port=9999, secure=true}
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:9999]
Jan 13, 2014 9:51:09 AM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.

Я использую Grizzly 2.2.1 и Jersey 1.12.

Огромное спасибо!


person user1389906    schedule 13.01.2014    source источник


Ответы (4)


IMO вы можете использовать другой метод Factory для инициализации защищенного сервера Grizzly HttpServer:

HttpServer secure = GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED,
                        ContainerFactory.createContainer(HttpHandler.class, rc),
                        true,
                        new SSLEngineConfigurator(sslCon));

Если вы инициализируете сервер таким образом, вам не нужно останавливаться и перенастраивать его снова.

Надеюсь, это поможет.

person alexey    schedule 13.01.2014
comment
Спасибо за ответ! Это не работает, но это привело меня к пути поиска, который, я надеюсь, приведет к решению. Теперь сервер запускается защищенным, но он умирает при рукопожатии, когда я пытаюсь использовать openssl s_client -connect localhost:9999. Я думаю, что мне просто нужно перенести все на новейшую версию Джерси, которая, насколько я понимаю, резко отличается от Джерси 1.12. Отпишусь, если разберусь. - person user1389906; 14.01.2014
comment
Вы можете включить отладку SSL: -Djavax.net.debug=all и посмотреть, почему рукопожатие не удается - person alexey; 15.01.2014
comment
Большое спасибо! Информация об отладке показала, что он пытался аутентифицировать клиента (чего я не хотел). Просматривая документацию гризли, я обнаружил, что при создании SSLEngineConfigurator я могу передавать логические значения, говорящие ему не аутентифицировать клиента. Это сделало это! - person user1389906; 15.01.2014
comment
Я думаю, что он имел в виду это: новый SSLEngineConfigurator(sslContextConfigurator).setNeedClientAuth(false) - person Rolf; 02.11.2015
comment
Не забудьте отключить клиентский режим, см. этот вопрос StackOverflow: > stackoverflow.com/questions/22724862/ - person Rolf; 03.11.2015

Извините, что так долго размещал это здесь. Ответ Алексея привел меня к рабочему решению, очень похожему на код Вольфганга Фаля. Вот что у меня получилось:

static HttpServer startSecureServer() throws IOException
{
    System.out.println("Starting server on port " + ConfigLoader.getHttpsServerPort());
    ResourceConfig rc = new PackagesResourceConfig("com.kinpoint.server.grizzlyresources");

    SSLContextConfigurator sslCon = new SSLContextConfigurator();

    sslCon.setKeyStoreFile(ConfigLoader.getKeystoreLocation()); // contains server keypair
    sslCon.setKeyStorePass(ConfigLoader.getKeystorePassword());

    HttpHandler hand = ContainerFactory.createContainer(HttpHandler.class, rc);

    HttpServer secure = GrizzlyServerFactory.createHttpServer(BASE_URI_SECURED, hand, true,
            new SSLEngineConfigurator(sslCon, false, false, false));

    return secure;
}

Второй параметр в SSLEngineConfigurator указывает не использовать режим клиента. Вот что меня смущало. Спасибо за помощь.

person user1389906    schedule 22.09.2014
comment
Это было очень полезно. Я заметил, что когда я запускаю свой сервер с поддельными учетными данными (расположение хранилища ключей/пароль), я не получаю никаких исключений, но служба недоступна. Выполняет ли ваш ConfigLoader некоторую проверку или вы нашли другой способ отлова ошибок? - person Amber; 03.02.2016

У меня есть хороший и проверенный пример с использованием Grizzly 2.3.3 в: https://github.com/danielnuriyev/scriptedstuff/tree/master/src/com/scriptedstuff/server

person Daniel Nuriyev    schedule 12.03.2014

Следующий код работает с Grizzly 2.3.7, а я использую Jersey 1.18 — он включает код для аутентификации клиента SSL — если у вас нет хранилищ ключей, эта функция будет просто проигнорирована.

/**
 * create a Server based on an url and possibly a ResourceConfig
 * 
 * @param url
 * @param rc
 * @param secure
 *          - true if SSL should be used
 * @param contextPath 
 * @return
 * @throws Exception
 */
public HttpServer createHttpServer(String url, ResourceConfig rc,
        boolean secure, String contextPath) throws Exception {
    // HttpServer result = GrizzlyServerFactory.createHttpServer(url, rc);
    // http://grepcode.com/file/repo1.maven.org/maven2/com.sun.jersey/jersey-grizzly2/1.6/com/sun/jersey/api/container/grizzly2/GrizzlyServerFactory.java#GrizzlyServerFactory.createHttpServer%28java.net.URI%2Ccom.sun.jersey.api.container.grizzly2.ResourceConfig%29
    HttpServer result = new HttpServer();
    final NetworkListener listener = new NetworkListener("grizzly",
            settings.getHost(), settings.getPort());
    result.addListener(listener);
    // do we need SSL?
    if (secure) {
        listener.setSecure(secure);
        SSLEngineConfigurator sslEngineConfigurator = createSSLConfig(true);
        listener.setSSLEngineConfig(sslEngineConfigurator);
    }
    // Map the path to the processor.
    final ServerConfiguration config = result.getServerConfiguration();
    final HttpHandler handler = ContainerFactory.createContainer(
            HttpHandler.class, rc);
    config.addHttpHandler(handler, contextPath);
    return result;
}

  /**
 * create SSL Configuration
 * 
 * @param isServer
 *          true if this is for the server
 * @return
 * @throws Exception
 */
private SSLEngineConfigurator createSSLConfig(boolean isServer)
        throws Exception {
    final SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
    // override system properties
    final File cacerts = getStoreFile("server truststore",
            "truststore_server.jks");
    if (cacerts != null) {
        sslContextConfigurator.setTrustStoreFile(cacerts.getAbsolutePath());
        sslContextConfigurator.setTrustStorePass(TRUSTSTORE_PASSWORD);
    }

    // override system properties
    final File keystore = getStoreFile("server keystore", "keystore_server.jks");
    if (keystore != null) {
        sslContextConfigurator.setKeyStoreFile(keystore.getAbsolutePath());
        sslContextConfigurator.setKeyStorePass(TRUSTSTORE_PASSWORD);
    }

    //
    boolean clientMode = false;
    // force client Authentication ...
    boolean needClientAuth = settings.isNeedClientAuth();
    boolean wantClientAuth = settings.isWantClientAuth();
    SSLEngineConfigurator result = new SSLEngineConfigurator(
            sslContextConfigurator.createSSLContext(), clientMode, needClientAuth,
            wantClientAuth);
    return result;
}
person Wolfgang Fahl    schedule 10.05.2014