Opis

Dokonałem testu Junit, który koncentruje się na próbie przetestowania połączenia z usługą SOAP Web Service.

Używam wbudowanego serwera TomCat dla mojego testu, aby uruchomić mój test za pomocą serwera Mock.

Używam również złączy HTTP i HTTPS.

Muszę użyć automatycznych portów zarówno dla tych złączy, ponieważ test działa na serwerze Jenkins i nie mogę po prostu użyć portu 443 lub 8443, ponieważ są już zajęte.

Rozumiem, że korzystanie z portu 0 jako standardowy port spowoduje, że Tomcat przy użyciu automatycznego alokacji portu, ale nie mogę zarządzać go z obu złączy.

Oczekiwane zachowanie

Chciałbym użyć automatycznej alokacji portu również dla mojego niestandardowego złącza SSL.

Czy można to zrobić w jakiś sposób?

Przykładowy kod

Oto kod dla mojej instancji Tomcat:

@Before
public void setup() throws Throwable {

    File tomcatWorkingDir = new File(mWorkingDir);

    //Empty the target/tomcat-working-dir directory if it exist
    //Create the directory otherwise
    if(tomcatWorkingDir.exists() && tomcatWorkingDir.isDirectory()){
        LOGGER.info("cleaning tomcat-working-dir directory");
        FileUtils.cleanDirectory(new File(mWorkingDir)); 
    } else {
        LOGGER.info("create tomcat-working-dir directory");
        tomcatWorkingDir.mkdir();
    }

    LOGGER.info("disabling ssl certification validation");
    //Disable JVM ssl sockets connection
    disableJVMCertificate();

    //Add server certificate
    createServerCertificate();

    //Custom SSL Connector
    Connector SSLConnector = getSSLConnector();

    mTomcat = new Tomcat();

    //Standard http startup port
    mTomcat.setPort(0);

    //Set up base directory 
    //Otherwise, tomcat would use the current directory
    mTomcat.setBaseDir(mWorkingDir);

    LOGGER.info("setting the ssl connector in TOMCAT");
    Service service = mTomcat.getService();
    service.addConnector(SSLConnector);

    //Redirect current port
    Connector defaultConnector = mTomcat.getConnector();
    defaultConnector.setRedirectPort(SERVER_HTTPS_PORT);

    //Configure the way WAR are managed by the engine
    mTomcat.getHost().setAutoDeploy(true);
    mTomcat.getHost().setDeployOnStartup(true);

    //Add mock server into our webApp
    String servletName = "/server";
    File webApp = new File(mWorkingDir,"../../../ws-mock-server/src/main/webapp");

    mTomcat.addWebapp(mTomcat.getHost(), servletName, webApp.getAbsolutePath());

    //start tomcat
    LOGGER.info("starting TOMCAT");

    mTomcat.start();
  }

I tutaj na moje niestandardowe złącze SSL.

    private static Connector getSSLConnector(){
    Connector connector = new Connector();
    connector.setPort(SERVER_HTTPS_PORT);
    connector.setSecure(true);

    //Http protocol Http11AprProtocol
    connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol");

    //Maximum threads allowedd on this instance of tomcat
    connector.setAttribute("maxThreads","200");
    connector.setAttribute("SSLEnabled", true);

    //No client Authentification is required in order to connect
    connector.setAttribute("clientAuth", false);

    //SSL TLSv1 protocol
    connector.setAttribute("sslProtocol","TLS");

    //Ciphers configuration describing how server will encrypt his messages
    //A common cipher suite need to exist between server and client in an ssl
    //communication in order for the handshake to succeed
    connector.setAttribute("ciphers","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");

    LOGGER.info("setting keystore file");
    //Here an absolute file path is needed in order to properly set up the keystore attribute
    connector.setAttribute("keystoreFile",new File(".").getAbsolutePath().replace("\\", "/")+"/"+mWorkingDir+"/server.jks");

    LOGGER.info("setting keystore pass");
    connector.setAttribute("keystorePass","changeit");

    return connector;
}
13
Florent M 17 luty 2017, 16:09

2 odpowiedzi

Najlepsza odpowiedź

Mam dwa rozwiązania tego problemu:

Wybierz port SSL ręcznie

Serversocket (0) Konstruktor Automatycznie wybiera darmowy port. Tomcat również używa tej metody.

try (ServerSocket testSocket = new ServerSocket(0)) {
    int randomFreePort = testSocket.getLocalPort(); 
    sslConnector.setPort(randomFreePort);
    defaultConnector.setRedirectPort( randomFreePort);
} // At this point the testSocket.close() called
tomcat.start();

Wiem, istnieje prawdopodobieństwo, że inny proces przypisuje ten sam port między {x0}} i tomcat.start(), ale możesz wykryć tę sytuację, z testem LifecycleState.FAILED.equals(sslConnector.getState()).

Używaj słuchaczy cyklicznych

Złącza TomCat są świadome cyklu cyklu, więc zostaniesz powiadomiony o wydarzeniach "przed" i "after_init". Tomcat inicjuje złącza w kolejności, jak dodałeś je do usługi.

  1. Dodaj złącze SSL.
  2. Dodaj złącze HTTP. (To będzie "domyślne" złącze. Nie nazywaj mTomcat.getConnector(), ponieważ otrzymuje pierwsze lub tworzy nowe złącze.)
  3. Po zakończeniu inicjalizacji złącza SSL można uzyskać wybrany port z GetLocalport () Call.
  4. Przed inicjalizacją złącza HTTP zadzwoń do Setredirectport

Pełny przykład:

    Tomcat mTomcat = new Tomcat();
    Connector sslConnector = getSSLConnector(); 
    mTomcat.getService().addConnector(sslConnector);    
    Connector defaultConnector = new Connector();
    defaultConnector.setPort(0);
    mTomcat.getService().addConnector(defaultConnector);

    // Do the rest of the Tomcat setup

    AtomicInteger sslPort = new AtomicInteger();
    sslConnector.addLifecycleListener(event->{
        if( "after_init".equals(event.getType()) )
            sslPort.set(sslConnector.getLocalPort());
    });
    defaultConnector.addLifecycleListener(event->{
        if( "before_init".equals(event.getType()) )
            defaultConnector.setRedirectPort(sslPort.get());
    });

    mTomcat.start();
2
Bukodi László 24 marzec 2017, 22:09

Nie próbowałem tego, ale z kodu wygląda

  1. Możesz uruchomić setRedirectPort po uruchomieniu serwera

  2. Możesz użyć Connector.getLocalPort, aby uzyskać rzeczywisty port

Myślę więc, że możesz spróbować dodać coś takiego

mTomcat.start(); // <-- your existing code
defaultConnector.setRedirectPort(SSLConnector.getLocalPort())
1
SergGr 27 luty 2017, 19:46