when I am creating Restservices
in java using GET
, POST
etc then I am requesting them using
http protocol
. as soon as i use https it gives error.
for eg : http://localhost:8080/demorest/webapi/aliens
is working properly.
but when I query same using https
https://localhost:8080/demorest/webapi/aliens
I get error site can not provide secured connection
what modification is required to make them compatible with https
.
As you mentioned you are new to APIs here is a detailed answer for you.
Answer is based on assumption that you are using tomcat server. There is 4 step approach to have application running on https, red below
If you dont already have ssl certificate generate yourself using keytool. Keytool is a certificate management utility provided together with the JDK, so if you have the JDK installed, you should already have keytool available.
Let's open our Terminal prompt and write the following command to create a JKS keystore:
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 3650 -storepass password
To create a PKCS12 keystore, and we should, the command is the following:
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650 -storepass password
Let's have a closer look at the command we just run:
genkeypair: generates a key pair;
alias: the alias name for the item we are generating;
keyalg: the cryptographic algorithm to generate the key pair;
keysize: the size of the key. We have used 2048 bits, but 4096 would be a better choice for production;
storetype: the type of keystore;
keystore: the name of the keystore;
validity: validity number of days;
storepass: a password for the keystore.
When running the previous command, we will be asked to input some information, but we are free to skip all of it (just press Return to skip an option). When asked if the information is correct, we should type yes. Finally, we hit return to use the keystore password as key password as well.
What is your first and last name?
[Unknown]: What is the name of your organizational unit?
[Unknown]: What is the name of your organization?
[Unknown]: What is the name of your City or Locality?
[Unknown]: What is the name of your State or Province?
[Unknown]: What is the two-letter country code for this unit?
[Unknown]: Is CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: yes
Enter key password for <tomcat>
(RETURN if same as keystore password):
Verify the keystore content To check the content of the keystore following the JKS format, we can use keytool again:
keytool -list -v -keystore keystore.jks
To test the content of a keystore following the PKCS12 format:
keytool -list -v -storetype pkcs12 -keystore keystore.p12
Convert a JKS keystore into PKCS12
Should we have already a JKS keystore, we have the option to migrate it to PKCS12; keytool has a convenient command for that:
keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12 -deststoretype pkcs12
2.) To Enable https in your project
If you have a application.properties file
server.port=8443
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=password
server.ssl.key-alias=tomcat
security.require-ssl=true
If you have application.yml file
server:
ssl:
key-store: classpath:keystore.p12
key-store-password: password
key-store-type: pkcs12
key-alias: tomcat
key-password: password
port: 8443
To achieve in application, we need to extend the WebSecurityConfigurerAdapter
class, since the security.require-ssl
property has been deprecated.
if you are on older version then you can skip below mentioned code.
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest()
.requiresSecure();
}
}
3.) Redirect http to https
Now that we have enabled HTTPS in our Spring Boot application and blocked any HTTP request, we want to redirect all traffic to HTTPS.
Spring allows defining just one network connector in application.properties (or application.yml)
. Since we have used it for HTTPS, we have to set the HTTP connector programmatically for our Tomcat web server.
@Configuration
public class ServerConfig {
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(getHttpConnector());
return tomcat;
}
private Connector getHttpConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}
}
4.) Distribute the SSL certificate to clients When using a self-signed SSL certificate, our browser won't trust our application and will warn the user that it's not secure. And that'll be the same with any other client.
It's possible to make a client trust our application by providing it with our certificate.
Extract an SSL certificate from a keystore We have stored our certificate inside a keystore, so we need to extract it. Again, keytool supports us very well:
keytool -export -keystore keystore.jks -alias tomcat -file myCertificate.crt
Make a browser trust an SSL certificate When using a keystore in the industry-standard PKCS12 format, we should be able to use it directly without extracting the certificate.
I suggest you check the official guide on how to import a PKCS12 file into your specific client.
If deploying the application on localhost, we may need to do a further step from our browser: enabling insecure connections with localhost
.
In Chrome, we can write the following URL in the search bar: chrome://flags/#allow-insecure-localhost
and activate the relative option.
Import an SSL certificate inside the JRE keystore To make the JRE trust our certificate, we need to import it inside cacerts: the JRE trust store in charge of holding all certificates that can be trusted.
First, we need to know the path to our JDK home. A quick way to find it, if we are using Eclipse or STS as our IDE, is by going to Preferences > Java > Installed JREs. If using IntelliJ IDEA, we can access this information by going to Project Structure > SDKs and look at the value of the JDK home path field.
Then, from our Terminal prompt, let's insert the following command (we might need to run it with administrator privileges by prefixing it with sudo):
keytool -importcert -file myCertificate.crt -alias tomcat -keystore $JDK_HOME/jre/lib/security/cacerts
you can refer project on github here