Monday, 26 June 2017

SSL with Embedded Tomcat without Spring Boot


In previous post, we have talked about how to have embedded tomcat without spring boot, now let see how to  enable SSL with embedded tomcat.


 

Step 1 : Use keytool to generate a self signed cert saved in keystore selfsigned.jks 

keytool -genkey -keyalg RSA -alias tomcat -keystore selfsigned.jks -storepass password -validity 360 -keysize 2048





Step 2 : Add a SSL connector to Tomcat server

package org.junjun.util.spring.server;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.http11.Http11NioProtocol;
import org.apache.log4j.Logger;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.junjun.util.spring.AppLauncher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class EmbeddedTomcat {
private static final Logger log = org.apache.log4j.Logger.getLogger(EmbeddedTomcat.class);
@Value("${tomcat.web.content.folder.path:src/main/webapp/}")
private String webContentFolder;
@Value("${tomcat.web.base.folder.path:target/}")
private String webBaseFolder;
@Value("${tomcat.port:7070}")
private String port;
@Value("${tomcat.ssl.enabled}")
private Boolean isSecured;
@Value("${tomcat.ssl.port}")
private String sslPort;
@Value("${tomcat.ssl.keystore.file}")
private String keyStoreFile;
@Value("${tomcat.ssl.keystore.password}")
private String keyStorePassword;
@Value("${tomcat.ssl.keystore.key.alias}")
private String keyAlias;
private Tomcat tomcat = new Tomcat();
private void addSslConnector(Tomcat tomcat) {
Connector con = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) con.getProtocolHandler();
con.setPort(new Integer(sslPort));
con.setSecure(Boolean.TRUE);
con.setScheme("https");
protocol.setSSLEnabled(Boolean.TRUE);
protocol.setKeystoreFile(keyStoreFile);
protocol.setKeystorePass(keyStorePassword);
protocol.setKeyAlias(keyAlias);
con.setAttribute("clientAuth", Boolean.FALSE);
con.setAttribute("sslProtocol", "TLS");
org.apache.catalina.Service service = tomcat.getService();
service.addConnector(con);
}
private void enforceSecuredChannel(StandardContext context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
@PostConstruct
public void start() throws Exception {
System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");
tomcat.setPort(Integer.valueOf(port));
tomcat.setBaseDir(webBaseFolder);
addSslConnector(tomcat);
StandardContext ctx = (StandardContext) tomcat.addWebapp("", webContentFolder);
ctx.setParentClassLoader(AppLauncher.class.getClassLoader());
enforceSecuredChannel(ctx);
tomcat.getConnector().setRedirectPort(new Integer(sslPort));
tomcat.start();
log.info("Tomcat Server Started at " + new Date());
tomcat.getServer().await();
}
@PreDestroy
public void stop() throws LifecycleException {
tomcat.stop();
}
}





Step 3 : Update server.properties for where is the keystore file and other SSL related configurations


# for embeded tomcat
tomcat.web.content.folder.path=${your.project}/src/main/webapp/
tomcat.web.base.folder.path=${your.project}/target/
tomcat.port=6060
tomcat.ssl.port=6443
tomcat.ssl.enabled=true
tomcat.ssl.keystore.file=${your.keystore.path}/selfsigned.jks
tomcat.ssl.keystore.password=changeit
tomcat.ssl.keystore.key.alias=tomcat




Step 4 : Run "ApplicationLauncher.java" and open https://localhost:6443/echo





Note : 

1. Because it is a self signed cert that's why it shows "Not Secure" on the browser.

2. The code has enforced all request redirect to secured channel which means requests to http://localhost:6060 would redirect to https://localhost:6443

3. You would need to download "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" and replace files US_export_policy.jar and local_policy.jar at ${JAVA_JRE_HOME}/lib/security.





JOB DONE




 

No comments:

Post a Comment

Flag Counter