javax.net.ssl.SSLException:<> 的证书与任何主题备用名称都不匹配:[]

javax.net.ssl.SSLException: Certificate for <> doesn't match any of the subject alternative names: []

当我尝试使用 Postman 命中 URL 时它工作正常,通过使用我个人的 cert.But 当我使用 Rest Assured 测试用例尝试相同时它抛出上述异常。

配置Class

public class Configuration {

    protected SSLConfig config = null;
    private static final Logger LOG = LoggerFactory.getLogger(Configuration.class);

    @SuppressWarnings("deprecation")
    @BeforeClass
    public void setKeystore()

    {
        KeyStore keyStore = null;

        KeyStore trustStore = null;
        try {
            String certPassword = System.getProperty("certPassword");
            String certPath = System.getProperty("certPath");

            String trustStorePassword = System.getProperty("trustStorePassword");
            String trustStorePath = System.getProperty("trustStorePath");
            Validate.notNull(certPath, "Path to Certificate on the file system cannot be null");
            Validate.notEmpty(certPassword, "Password cannot be empty");
            Validate.notNull(trustStorePath, "Path to trustStore on the file system cannot be null");
            Validate.notEmpty(trustStorePassword, "TrustStore Password cannot be empty");

            keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream(certPath), certPassword.toCharArray());
            trustStore = KeyStore.getInstance("JKS");
            trustStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());

            if (keyStore != null) {

                org.apache.http.conn.ssl.SSLSocketFactory clientAuthFactory = new org.apache.http.conn.ssl.SSLSocketFactory(
                        keyStore, certPassword, trustStore);
                config = new SSLConfig().with().sslSocketFactory(clientAuthFactory).and().allowAllHostnames();

            }
            EnvironmentConstants.getEnvironment();

        } catch (Exception e) {
            LOG.error("Error while loading keystore");
            e.printStackTrace();
        }
    }

    @BeforeTest
    public Properties loadproperties() {

        InputStream input = getClass().getClassLoader().getResourceAsStream("errorMessages.properties");
        Properties properties = new Properties();
        try {
            properties.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

}

这个问题是因为,我们公司配置了新服务器,但没有在服务器中包含 DNS cert.So 我公司在 cert.Now 中包含服务器名称,它正在工作。

根据RFC 2818 (the HTTPS specification)

If the hostname is available, the client MUST check it against the server's identity as presented in the server's Certificate message, in order to prevent man-in-the-middle attacks... If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.

您应该生成带有 SAN 扩展名的证书,其中包含您计划使用该证书的所有主机名:

keytool -genkeypair \
    -keystore server-keystore.pkcs12 \
    -deststoretype pkcs12 \
    -dname "CN=mydomain.local" \
    -keypass changeit \
    -storepass changeit \
    -keyalg RSA \
    -validity 1825 \
    -keysize 4096 \
    -alias mydomain.local \
    -ext SAN=dns:mydomain.local,dns:mydomain.dev,dns:mydomain.test,dns:localhost

如果您只想使用 REST Assured 成功请求,您可以尝试使用方法 .allowAllHostnames() for SSLConfig

这样客户端就不会验证主机名。