简体   繁体   中英

configure embedded Tomcat7 to use keystorefile embedded in executable jar

I've managed to configure my embedded tomcat to use a keystorefile and it works when i execute the project from eclipse.

The code is simple:

...
String keystore = new File(MyServer.class.getResource("/keystore").toURI()).toPath().toString();
httpsConnector.setAttribute("keystoreFile",keystore);
...

The file keystore is located in a source directory added to the buildpath.

After exporting the project to an executable jar, i can verify the existence of the keyfile in the root of the jar.

But on executing the jar, i get this error:

Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical

So i asume, that i can not configure the keyfile with httpsConnector.setAttribute("keystoreFile",...) . is there another way to configure that? i really dont want to copy the keyfile in a temp dir and reference it from there.

i really dont want to copy the keyfile in a temp dir and reference it from there.

I sympathize, but it looks like you will have to just that. A Java keystore can be loaded from any type of input stream (see Keystore.load ) so you would think it would be possible to load your keystore from a resource in the jar file. However if you search the Tomcat 7 source code for the string "ks.load" you will see that it always interprets the keystoreFile attribute as the name of a File and creates a FileInputStream which it then passes the ks.load.

Therefore it will be necessary to create the temp file containing the keystore and pass the location of this file as your keystoreFile attribute.

BTW - if you are not intending to distribute this jar and are willing to keep it private, then your approach of embedding the keystore is probably OK.

However if you are planning on distributing this jar to multiple sites, then the security of every site is based on the same private key. Furthermore, anyone with access to the jar file can probably extract the private key and can then eavesdrop or perhaps man-in-the-middle attack all of your sites.

In general it is better to have an installation process that requires a new private key and certificate to be generated by the administrator of the site (even if it's just a self-signed certificate). That way every key is different and the only way to compromise the site would be to get access to that servers key store and password.

This might be an old post, but I encountered the same problem and didn't found a solution online. So I want to share what I did.

In my case, I needs two ports both with self-signed certificates. Besides the one configured in application.yml, the other port is configured in the main entry.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ServletWebServerFactory servletContainer() throws IOException
    {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(additionalConnector());
        return tomcat;
    }


    private Connector additionalConnector() throws IOException
    {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("https");
        connector.setPort(8088);
        ...

        URL keystore = new ClassPathResource("keystore.jks").getURL();
        connector.setAttribute("keystoreFile", keystore.toExternalForm());
        return connector;
    }
}

Using URL, both mvn spring-boot:run and run the jar work and can load the keystore without problem.

I was using spring-boot 2.0.1.RELEASE and tomcat 8.5.29

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM