首页 > 解决方案 > 为什么我的 Rest Assured POST 方法不能接受所有主机?

问题描述

javax.net.ssl.SSLException: Certificate for 
"censored.local" doesn't match any of the subject alternative 
names: [censored.com, *.censored.com]

我的测试课:

...
.given().spec(reqSpec)
...

我的配置类:

public abstract class Configurator {
    protected static TestEnv envConf = chooseEnv();
    protected static RequestSpecification reqSpec;
    static { try { reqSpec = configureRestAssured(); } catch (Exception e) {e.printStackTrace(); } }

    protected static TestEnv chooseEnv() {
        // Some logic following to select an instance from TestEnv (not shown here)
        ...    
        envConf = TestEnv.BETA;
        return envConf;
    }
    protected static RequestSpecification configureRestAssured() {
        RequestSpecification reqSpec = new RequestSpecBuilder().build();
        reqSpec
                .header("Authorization", String.format("Bearer %s", envConf.getBearerToken()))
                // This gets the censored.local URI:
                .baseUri(envConf.getBaseURI())

                .config(getRAconfig());
        return reqSpec;
    }
    private static RestAssuredConfig getRAconfig() {
        SSLSocketFactory sslSocket = getSSLsocket (envConf.getKeystoreFile(), "keystorePassword", "PrivateKeyPassword");
        RestAssuredConfig raConfig = RestAssuredConfig.config()
        .sslConfig(SSLConfig.sslConfig().sslSocketFactory(sslSocket));
        return raConfig;
    }
    private static SSLSocketFactory getSSLsocket(String ksPath, String ksPassword, String pkPassword) {
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(new FileInputStream(ksPath), ksPassword.toCharArray());
        SSLContext context = SSLContexts.custom()
                .loadKeyMaterial(keystore, pkPassword.toCharArray(), firstPrivateKeyStrategy())
                .loadTrustMaterial(trustEveryoneStrategy())
                .build();
        return new SSLSocketFactory(context);
    }
    private static PrivateKeyStrategy firstPrivateKeyStrategy() {
        return new PrivateKeyStrategy() {
            @Override
            public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
                return aliases.keySet().iterator().next();
            }
        };
    }
    private static TrustStrategy trustEveryoneStrategy() {
        return new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
                return true;
            }
        };
    }}
raConfig = {RestAssuredConfig@2752} 
 configs = {HashMap@2753}  size = 17
  ... 
  {Class@2003} "class io.restassured.config.SSLConfig" -> {SSLConfig@3257} 
   key = {Class@2003} "class io.restassured.config.SSLConfig"
   value = {SSLConfig@3257} 
    pathToKeyStore = null
    pathToTrustStore = null
    keyStorePassword = null
    trustStorePassword = null
    keyStoreType = "pkcs12"
    trustStoreType = "pkcs12"
    port = -1
    trustStore = null
    keyStore = null
    x509HostnameVerifier = {StrictHostnameVerifier@3286} "STRICT"

STRICT 基本上是在显示我的问题吗?如果是这样,如何破解非严格的 x509HostnameVerifier?

标签: javasslhttpsapache-httpclient-4.xrest-assured

解决方案


我找到了根据需要自定义 SSL 配置的方法。附有轻微审查的代码。寻找“圣杯”评论:

 protected static RequestSpecification configureRestAssured() {
    // Create the ReqSpec instance:
    RequestSpecification reqSpecToBuild = new RequestSpecBuilder().build();
    // Configure more simple stuff for common request specification:
    reqSpecToBuild
            .header("Content-Type", "application/json")
            .baseUri(envConf.getBaseURI())
            .config(getRAconfig());
    return reqSpecToBuild; 
    }
// Add extended config object to the request spec:
private static RestAssuredConfig getRAconfig() {
    // Create a special socket with our keystore and ALLOW_ALL_HOSTNAME_VERIFIER:
    SSLSocketFactory sslSocket = getSSLsocket (envConf.getKeystoreFile(), somePass, somePass);
    // Create a configuration instance to load into the request spec via config():
    RestAssuredConfig raConfigToBuild = RestAssuredConfig.config()
            // Set SSL configuration into the RA configuration, with an SSLConfig object, that refers to our socket:
            .sslConfig(SSLConfig.sslConfig().sslSocketFactory(sslSocket));
    return raConfigToBuild;
}
private static SSLSocketFactory getSSLsocket(String ksPath, String ksPassword, String pkPassword) {
    KeyStore keystore = KeyStore.getInstance("PKCS12");
    // Load keystore file and password:
    keystore.load(new FileInputStream(ksPath), ksPassword.toCharArray());
    SSLContext context = SSLContexts.custom()
            .loadKeyMaterial(keystore, pkPassword.toCharArray())
            .build();
    // This is the holy grail:
    SSLSocketFactory sslSocketToBuild = new SSLSocketFactory(context, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    return sslSocketToBuild;
}
}

请注意,我不仅为 SSLSocketFactory 的构造函数提供了一个参数,而且还提供了常规参数(上下文)以及 ALLOW_ALL_HOSTNAME_VERIFIER 参数 - 这会有所不同!


推荐阅读