Category Archives: Java

Java + HTTPS: Unable to Find Valid Certification Path to Requested Target

PROBLEM

When invoking a HTTPS URL from Java, for example…

final RestTemplate restTemplate = new RestTemplate();
restTemplate.execute("https://www.google.com/some-api", HttpMethod.GET, null, ...);

…the following exception is thrown…

org.springframework.web.client.ResourceAccessException: I/O error on GET 
request for "https://www.google.com":sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target; nested exception 
is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:607)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)

SOLUTION 1: Disable SSL Validation – NOT RECOMMENDED

One way is to simply disable the SSL validation by configuring SSLContext to trust all X.509 certificates before invoking the intended HTTPS URL.

@Configuration
class MyAppConfig {
    @Bean
    public Boolean disableSSLValidation() throws Exception {
        final SSLContext sslContext = SSLContext.getInstance("TLS");

        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }}, null);

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        return true;
    }
}

Unless you are writing test cases or implementing non-production code, this approach is highly discouraged because it doesn’t prevent the man-in-the-middle attacks.

SOLUTION 2: Import Certificate into Java Keystore – RECOMMENDED

The reason we see this exception is because the certificate used by the HTTPS URL doesn’t exist in the Java Keystore. Hence, the SSL validation fails.

To fix this, we can download the website’s certificate using a browser to be added into Java Keystore.

Access the website (in this example, I use https://www.google.com) and click on the pad lock.

Find the button that allows you to view and export the certificate as a PEM file. In this example, I named that file google.cer.

The content of the downloaded PEM file should look like this:-

-----BEGIN CERTIFICATE-----
MIIEgDCCA2igAwIBAgIITq9JKLrGf5EwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
eoV23mHmV6/0mOwocVYt/Th96WNGGmhANkFW//HCphRWnhaOqIG6yFRQ/jxArTvZ
QJEGI5AiYHzQn7LdUM8mH1o3ifR+lX+QiAwyeU9oegdlRslI2KMoPOuOFj329NFx
Bw+XVQXMsRJITPg8pnegPmLCOjpz8y7pBxbxGnfaI66I8X4dArsaXX4r5mkfhk2e
mm7fxQ8qUaW9mKoW0XvwGxU0AwKI8OopuXHoD97vr2GSK0QNZ19A96mtTWnQ2cu2
i9qjGw==
-----END CERTIFICATE-----

Go to the Terminal.

If you have multiple versions of java, make sure you choose the correct version first:-

export JAVA_HOME="`/usr/libexec/java_home -v '1.7*'`"

Import the certificate into Java Keystore:-

sudo keytool -import -trustcacerts -file /path/to/google.cer -alias google -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit

Now, you should be able to invoke the HTTPS URL without any exception.

If for some reason you need to remove the imported certificate from Java Keystore, you can refer to that certificate using the alias and run this command:-

sudo keytool -delete -alias google -keystore $JAVA_HOME/jre/lib/security/cacerts

Java + HTTPS: Handling ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY

PROBLEM

When accessing HTTPS links from a local application server, the modern browser throws the following error message(s):-

  • SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message. (Error code: ssl_error_weak_server_ephemeral_dh_key)
  • Server has a weak ephemeral Diffie-Hellman public key

SOLUTIONS

There are multiple solutions to this problem.

SOLUTION 1: Disable browser check

One way is to completely disable this check on the browser.

For example, in Firefox, go to about:config and set security.ssl3.dhe_rsa_aes_128_sha and security.ssl3.dhe_rsa_aes_256_sha to false.

The downside is the browser is exposed to Logjam attacks.

SOLUTION 2: Use Java 8

The easiest solution is to use Java 8 because it has better cipher support.

The downside is sometimes using Java 8 is not an option if you don’t have control on the application server.

SOLUTION 3: Use Bouncy Castle

If you are using Java 6 or Java 7, you can download Bouncy Castle crypto implementation and store them in $JAVA_HOME/jre/lib/ext.

Then, register this provider in $JAVA_HOME/jre/lib/security/java.security, for example:-

#
# List of providers and their preference orders (see above):
#
# MacOSX added com.apple.crypto.provider.Apple as #3
security.provider.1=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-macosx.cfg
security.provider.2=sun.security.provider.Sun
security.provider.3=com.apple.crypto.provider.Apple
security.provider.4=sun.security.rsa.SunRsaSign
security.provider.5=com.sun.net.ssl.internal.ssl.Provider
security.provider.6=com.sun.crypto.provider.SunJCE
security.provider.7=sun.security.jgss.SunProvider
security.provider.8=com.sun.security.sasl.Provider
security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.10=sun.security.smartcardio.SunPCSC
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider

The downside is if your team is doing local application development, all team members have to perform these steps on their machines too.

SOLUTION 4: Disable all weak Diffie-Hellman ciphers

Another solution is to configure the server by disabling all the weak Diffie-Hellman ciphers.

You can either enable the strong ciphers or disable the weak ciphers.

However, it is preferable (in my opinion) to disable weak ciphers so that newer (and stronger) ciphers will automatically be included when Java version is updated in the future.

Here is a working example for Jetty server:-

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>8.1.16.v20140903</version>
    <configuration>
        <stopKey>jetty-stop-key</stopKey>
        <stopPort>7778</stopPort>
        <scanIntervalSeconds>1</scanIntervalSeconds>
        <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog">
            <extended>true</extended>
            <logTimeZone>CST</logTimeZone>
        </requestLog>
        <webApp>
            <contextPath>/${project.artifactId}</contextPath>
            <webInfIncludeJarPattern>.*/.*jsp-api-[^/]\.jar$|./.*jsp-[^/]\.jar$|./.*taglibs[^/]*\.jar$</webInfIncludeJarPattern>
        </webApp>
        <connectors>
            <connector implementation="org.eclipse.jetty.server.bio.SocketConnector">
                <port>7777</port>
            </connector>
            <connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">
                <port>7443</port>
                <keystore>${project.basedir}/src/main/config/keystore.jks</keystore>
                <keyPassword>jetty8</keyPassword>
                <password>jetty8</password>
                <excludeCipherSuites>
                    <excludeCipherSuites>SSL_RSA_WITH_DES_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_DHE_RSA_WITH_DES_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_DHE_DSS_WITH_DES_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_RSA_EXPORT_WITH_RC4_40_MD5</excludeCipherSuites>
                    <excludeCipherSuites>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</excludeCipherSuites>
                    <excludeCipherSuites>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</excludeCipherSuites>
                </excludeCipherSuites>
            </connector>
        </connectors>
    </configuration>
</plugin>

The downside is the server configuration gets a little lengthy.

Java: Builder for Immutable POJO

PROBLEM

Let’s assume we have an immutable Person object:-

public final class Person implements Serializable {
    private final String name;
    private final Collection<Car> cars;

    public Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = MoreObjects.firstNonNull(cars, ImmutableList.<Car>of());
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

… and an immutable Car object:-

public final class Car implements Serializable {
    private final String license;
    private final LocalDate boughtOn;

    public Car(final String license, final LocalDate boughtOn) {
        this.license = license;
        this.boughtOn = boughtOn;
    }

    public String getLicense() {
        return license;
    }

    public LocalDate getBoughtOn() {
        return boughtOn;
    }
}

To create the Person object, we need to write something like this:-

final Person person = new Person("Mike",
                                 Collections.singletonList(
                                     new Car("123", new LocalDate(2015, 1, 1))));

If the POJO has a lot of properties, it becomes very difficult to keep track all the constructor argument positions.

SOLUTION

@mkarneim wrote a POJO Builder that creates the builder class(es) at compilation time.

To pull this off, we need to add the following dependency with provided scope.

<dependency>
    <groupId>net.karneim</groupId>
    <artifactId>pojobuilder</artifactId>
    <version>3.4.0</version>
    <scope>provided</scope>
</dependency>

Next, annotate with the Person constructor with @GeneratePojoBuilder. Make the constructor visibility to protected so that no one can directly instantiate that object.

public final class Person implements Serializable {
    private final String name;
    private final Collection<Car> cars;

    @GeneratePojoBuilder
    protected Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = MoreObjects.firstNonNull(cars, ImmutableList.<Car>of());
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

Do the same for Car object:-

public final class Car implements Serializable {
    private final String license;
    private final LocalDate boughtOn;

    @GeneratePojoBuilder
    protected Car(final String license, final LocalDate boughtOn) {
        this.license = license;
        this.boughtOn = boughtOn;
    }

    public String getLicense() {
        return license;
    }

    public LocalDate getBoughtOn() {
        return boughtOn;
    }

Next, and this is probably the most important step… run mvn clean compile to generate the builder classes. This allows the IDE to help us with code completion when using the builders.

Now, we can create the Person object like this:-

final Person person = new PersonBuilder()
        .withCars(ImmutableList.of(
                new CarBuilder()
                        .withBoughtOn(new LocalDate(2015, 1, 1))
                        .withLicense("123")
                        .build()))
        .withName("Mike")
        .build();

If you are running the program directly from IntelliJ, we need to ensure the program is compiled using Maven. To do this, edit the configuration for the runner class:-

Remove the default Make task:-

Add Maven goals:-

Enter clean and compile:-

Now, when IntelliJ runs the program, the program will be compiled using Maven to ensure no compilation errors on the builder classes during execution.

IntelliJ IDEA 14.1: Better equals(), hashCode() and toString()

PROBLEM

Let’s assume we want to create the default equals(), hashCode() and toString() with the following bean:-

public final class Person {
    private final String name;
    private final Collection<Car> cars;

    public Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = cars;
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

Most IDEs, including older version of IntelliJ, have code generation features that would create something similar to this:-

public final class Person {
    ...

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        final Person person = (Person) o;

        if (name != null ? !name.equals(person.name) : person.name != null) {
            return false;
        }
        return !(cars != null ? !cars.equals(person.cars) : person.cars != null);
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (cars != null ? cars.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Person{" +
               "name='" + name + '\'' +
               ", cars=" + cars +
               '}';
    }
}

While it works, the generated code is usually crazy horrendous.

SOLUTION

With IntelliJ 14.x, it allows us to select templates from several proven libraries.

To generate equals() and hashCode(), select equals() and hashCode() option from the Generate pop-up dialog:-

There are several templates to choose from:-

Here’s an example of equals() and hashCode() using Guava and getter methods:-

public final class Person {
    ...

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final Person person = (Person) o;
        return Objects.equal(getName(), person.getName()) &&
               Objects.equal(getCars(), person.getCars());
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(getName(), getCars());
    }
}

To generate toString(), select toString() option from the Generate pop-up dialog:-

Again, there are several templates to choose from:-

Here’s an example of toString() using Guava:-

public final class Person {
    ...

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("name", name)
                .add("cars", cars)
                .toString();
    }
}

IntelliJ IDEA: Generating Immutable Classes and Fields

PROBLEM

By default, IntelliJ IDEA generates mutable classes and fields.

One of the steps to achieve immutability is to make all classes and fields to be final.

SOLUTION

Making Fields Final

Go to Preferences... -> Code Style -> Java -> Code Generation tab

Under Final Modifier, check both Make generated local variables final and Make generated parameters final.

Making Classes Final

Go to Preferences... -> File and Code Templates -> Templates tab

Select Class and add final.

Better Preconditions: v0.1.0

DEPENDENCY

<dependency>
  <groupId>com.github.choonchernlim</groupId>
  <artifactId>better-preconditions</artifactId>
  <version>0.1.0</version>
</dependency>

Introduction

The goal of Better Preconditions is to provide a set of Java APIs that allows developers to create succinct, yet readable and testable preconditions.

Why Write Preconditions?

Let’s assume we have the following code:-

public void save(final String name, final LocalDate birthDate) {
    dao.save(new Entity(name.toUpperCase(), birthDate));
}

Although this example is simple and trivial, every developer that looks at this code will interpret this API differently. For example:-

  • Can name be blank?
  • What if we pass in a null value for name?
  • Can birth date be null?
  • Can birth date be after today’s date?

The truth of the matter is we cannot create an API that handles every possible scenario. Otherwise, we will never get our products out the door.

Thus, it is better to safeguard our API with a set of preconditions to ensure our fellow developers (or even you) know what this API needs before it performs the real work. Further, it provides a living documentation that would never go stale. Here’s an example of what the preconditions might look like:-

public void save(final String name, final LocalDate birthDate) {
    // precondition 1: name cannot be blank
    // precondition 2: birth date cannot be null
    // precondition 3: birth date cannot be after today's date

    dao.save(new Entity(name.toUpperCase(), birthDate));
}

What’s wrong with Guava Preconditions?

The biggest advantage of using Guava Preconditions is its flexibility. The biggest disadvantage of it is also its flexibility. Here’s an example written with Guava Preconditions:-

public void save(final String name, final LocalDate birthDate) {
    checkArgument(!nullToEmpty(name).trim().isEmpty(), "Name cannot be blank");
    checkNotNull(birthDate, "Birth date cannot be null");
    checkArgument(!birthDate.isAfter(LocalDate.now()), "Birth date cannot be after today's date");

    dao.save(new Entity(name.toUpperCase(), birthDate));
}

A couple of observations:-

  • Too verbose, which makes the code very messy. If we start inserting the raw values into the error messages, it becomes even messier.
  • We use checkArgument(..) and checkNotNull(..) most of the time. When an exception is thrown, we either get IllegalArgumentException or NullPointerException. This makes the API very confusing to unit test if there are many preconditions.

Introducing the power of Better Preconditions

Let’s rewrite the example above with Better Preconditions:-

public void save(final String name, final LocalDate birthDate) {
    expect(name, "Name")
            .not().toBeBlank()
            .check();

    expect(birthDate, "Birth Date")
            .not().toBeNull()
            .not().toBeAfter(LocalDate.now(), "Today's Date")
            .check();

    dao.save(new Entity(name.toUpperCase(), birthDate));
}

A couple of observations:-

  • Short and succinct.
  • Each thrown exception provides very useful error message for debugging purpose. For example, if birth date is after today’s date, the error message would be Birth Date [ 2015-02-01 ] must not be after Today's Date [ 2015-01-01 ]
  • When one of the preconditions fails, a specific exception is thrown. For example:-
    • blank name throws StringBlankPreconditionException
    • null birth date throws ObjectNullPreconditionException
    • birth date after today’s date throws JodaTimeAfterPreconditionException

    This makes it simpler to unit test because we can easily catch specific exception without any doubts.

Conclusion

Lastly, play around with it. This post barely scratches the surface of what Better Preconditions can do for you. If it works for you, great. If it doesn’t work for you and you are still interested to use it, create an issue at my GitHub page so that I can fix it. Due to my current real world workload, I’m using the 80/20 rule… the provided APIs should solve 80% of the problem.

To learn more about Better Preconditions, visit https://github.com/choonchernlim/better-preconditions

Spring Security: Invalid CSRF Token ‘null’ was found on the request parameter ‘_csrf’ or header ‘X-CSRF-TOKEN’

PROBLEM

With Spring Security 4.x, the CSRF protection is enabled by default. You may disable it, but to be more aligned with OWASP and the industry security standard, it’s best to leave this setting the way it is. Learn more about CSRF attack…

To prevent this attack, Spring Security 4.x requires you to attach a server-side generated CSRF token on any POST, PUT or DELETE calls… basically, actions that may modify the request state. Their argument for not attaching this token on GET is to prevent this token value from leaking out.

Further, you will require to call POST /login and POST /logout now. In the past, you can call GET /j_spring_security_logout without problem.

If you invoke POST, PUT or DELETE without this CSRF token, you will get a 403 error with this message: "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.".

SOLUTION

To obtain this CSRF token, add this Spring Security custom tag to the JSP file:-

<!DOCTYPE html>
<html>
	<head>
	    <sec:csrfMetaTags/>
	</head>
	<body>
	</body>
</html>

The rendered HTML looks like this:-

<!DOCTYPE html>
<html class="no-js">
	<head>
	    <meta name="_csrf_parameter" content="_csrf" />
	    <meta name="_csrf_header" content="X-CSRF-TOKEN" />
	    <meta name="_csrf" content="e62835df-f1a0-49ea-bce7-bf96f998119c" />
	</head>
	<body>
	</body>
</html>

Finally, set the request header before making the AJAX call:-

var header = $("meta[name='_csrf_header']").attr("content");
var token = $("meta[name='_csrf']").attr("content");

$.ajax({
    url: '/test',
    type: 'POST',
    beforeSend: function(xhr){
        xhr.setRequestHeader(header, token);
    },
    success: function(data) {
        console.log(data);
    },
    error: function (xhr, ajaxOptions, thrownError) {
        console.log(xhr.status + ": " + thrownError);
    }
});