Java applications that communicate over SSL/TLS may encounter certificate exceptions, which can prevent successful connections. One common exception is java.security.cert.CertificateException: No subject alternative names present
, indicating that the server’s certificate lacks subject alternative names (SANs) or does not match the requested hostname or IP address.
To understand and resolve this issue, let’s first examine how SSL/TLS certificates work and what SANs are. An SSL/TLS certificate is issued to a specific domain or IP address and contains information about the entity it was issued to, including its public key and identity details (e.g., organization name, country). The SAN extension allows multiple hostnames or IP addresses to be associated with a single certificate.
When a Java client connects to an SSL/TLS server using a URL like https://example.com
, it checks the server’s certificate to ensure that:
- The certificate is issued by a trusted Certificate Authority (CA).
- The certificate has not expired or been revoked.
- The certificate matches the requested hostname or IP address.
If any of these checks fail, the client throws an exception.
Now, let’s discuss how to resolve the java.security.cert.CertificateException: No subject alternative names present
exception:
Solution 1: Modify the Server Certificate
To fix this issue, you can modify the server’s certificate by adding SANs that include the requested hostname or IP address. You can use tools like OpenSSL to generate a new certificate with the required SANs.
Here are the general steps:
- Generate a new private key and certificate signing request (CSR) using OpenSSL.
- Create a certificate configuration file (
openssl.cnf
) that includes the SAN extension. - Use OpenSSL to generate a self-signed certificate or send the CSR to a CA for signing.
- Convert the certificate to the required format (e.g., PKCS12, JKS).
- Import the certificate into your Java keystore.
Solution 2: Update the Client Configuration
If modifying the server’s certificate is not feasible, you can update the client configuration to disable SSL verification or use a custom hostname verifier. However, be aware that disabling SSL verification compromises security and should only be done for testing purposes.
Here are some code examples:
- Disable SSL verification using a trust manager:
import javax.net.ssl.;
import java.security.;
public class CustomTrustManager {
public static void disableSslVerification() throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
}
* Use a custom hostname verifier:
```java
import javax.net.ssl.*;
import java.security.*;
public class CustomHostnameVerifier {
public static void setCustomHostnameVerifier() {
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
Solution 3: Update the Java System Properties
In some cases, updating the Java system properties can resolve the issue. For example, you can add the following property to your Java command line:
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
This property disables endpoint identification for LDAP connections.
Conclusion
Resolving java.security.cert.CertificateException: No subject alternative names present
exceptions requires understanding how SSL/TLS certificates work and what SANs are. By modifying the server’s certificate, updating the client configuration, or adjusting Java system properties, you can resolve this issue and establish secure connections between your Java application and the target server.
Best Practices
When working with SSL/TLS certificates in Java, keep the following best practices in mind:
- Always validate server certificates to ensure their authenticity and integrity.
- Use trusted Certificate Authorities (CAs) to sign your certificates.
- Regularly update your keystore and truststore to include new CA certificates and revocation lists.
- Avoid disabling SSL verification or using custom hostname verifiers unless absolutely necessary, as these practices compromise security.
By following these guidelines and understanding how to resolve common certificate exceptions, you can ensure secure and reliable communication between your Java application and external servers.