Jetty

References

Create a maven web application project:

$ mvn archetype:generate -DgroupId=tld.domain -DartifactId=example-server -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0

To run the web application, we configure the maven-jetty-plugin.

maven-jetty-plugin

Add the following configuration to project’s pom.xml.

1
2
3
4
5
6
7
8
9
10
<build>
  <finalName>example-server</finalName>
  <plugins>
    <plugin>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>maven-jetty-plugin</artifactId>
      <version>6.1.26</version>
    </plugin>
  </plugins>
</build>

To run the server

$ mvn jetty:run

As soon as the server is started you can enter the following url in your browser http://localhost:8080/example-server

As you can see, the server is started and listens on port 8080 by default. If you want to change this, it can easily be configured. Just extend the plugin with a configuration element and add a connector.

1
2
3
4
5
6
7
8
9
10
11
12
<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <version>6.1.26</version>
  <configuration>
    <connectors>
      <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
        <port>9090</port>
      </connector>
    </connectors>
  </configuration>
</plugin>

Run Jetty server

$ mvn jetty:run

As soon as the server is started you can enter the following url in your browser http://localhost:9090/example-server

maven-jetty-plugin with TLS/SSL support

Generate certificates from letsencrypt.org. You will have

  • cert.pem is certificate for your domain, public key
  • chain.pem is intermediate certificate
  • fullchain.pem is the chain of trust, certificate chain, or CA bundle
  • privkey.pem is the private key

Convert certificate chain + private key to the PKCS#12 file format

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12

Convert PKCS#12 file into Java keystore format

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit -destkeystore keystore.jks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass changeit

Don’t need the PKCS#12 file anymore

$ rm keystore.p12

Simply add the following connector element and make sure the keystore.jks is located in your example-server directory.

1
2
3
4
5
6
<connector implementation="org.mortbay.jetty.security.SslSocketConnector">
  <port>9443</port>
  <keystore>${basedir}/keystore.jks</keystore>
  <password>password</password>
  <keyPassword>password</keyPassword>
</connector>

Run Jetty server

$ mvn jetty:run

As soon as the server is started you can enter the following url in your browser https://localhost:9443/example-server

You can test this in a nice way using openssl to see what the server returns when you try to access it on port 9443.

$ openssl s_client -connect localhost:9443

Finally, if you for some reason want mutual authentication, you also need to specify a trust store in which the server keeps certificates of trusted clients. Extend the previous connector with the following information:

1
2
3
4
5
6
7
8
9
<connector implementation="org.mortbay.jetty.security.SslSocketConnector">
  <port>9443</port>
  <keystore>${basedir}/keystore.jks</keystore>
  <password>password</password>
  <keyPassword>password</keyPassword>
  <truststore>${basedir}/serverTruststore.jks</truststore>
  <trustPassword>password</trustPassword>
  <needClientAuth>true</needClientAuth>
</connector>

Now you have a web server up and running your web application with mutual authentication. The clients must provide a valid certificate in order to communicate with the server. At last I just want to add a final element to our configuration. Since TLS/SSL can be quite horrible to troubleshoot, I add the following configuration which gives a lot of nice output :)

1
2
3
4
5
6
<systemProperties>
  <systemProperty>
    <name>javax.net.debug</name>
    <value>ssl</value>
  </systemProperty>
<systemProperties>