java - 为什么我的 Rest Assured POST 方法不能接受所有主机?

标签 java ssl https apache-httpclient-4.x rest-assured

  • 我们的目标服务器 (censored.local) 拥有 CN = censored.com, *.censored.com 的 HTTPS 证书
  • 测试引发异常:
javax.net.ssl.SSLException: Certificate for 
"censored.local" doesn't match any of the subject alternative 
names: [censored.com, *.censored.com]
  • 我明白为什么会发生这种情况 (RFC 2818),但出于测试目的我想绕过它。无法在目标服务器上安装不同的证书。
  • .relaxedHTTPSValidation() 和 .allowAllHostnames() 无效。因此,我尝试编写代码:

我的测试类:

...
.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 基本上显示了我的问题吗? 如果是这样,如何破解非 STRICT x509HostnameVerifier?

最佳答案

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

 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 参数 - 这造成了不同!

关于java - 为什么我的 Rest Assured POST 方法不能接受所有主机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58524924/

相关文章:

java - 如何从 jsoup 请求更改远程 IP 地址?

java - java NIO SSO 处理器中的空指针

android - Android Studio 上未知的 ssl3 警报证书到 mosquitto 代理

ssl - Comodo 通配符 ssl 证书和 Haproxy

Apache、Tomcat 和 SSL : ProxyPass and ProxyPassReverse

java - 如何在 neo4j 中使用条件匹配

java - 在 Eclipse IDE 中使用 JDBC 检索数据时出现问题

iOS NSURLAuthenticationMethodClientCertificate 未请求与 ActiveSync 服务器

apache - 如何通过 https 使用 Vagrant & Puppet

java - token 语法错误,预期 ConstructorHeaderName 和 token 语法错误 "(",< 预期