【问题标题】:Why can't I accept all hosts for my Rest Assured POST method?为什么我的 Rest Assured POST 方法不能接受所有主机?
【发布时间】:2019-10-23 14:16:33
【问题描述】:
  • 我们的目标服务器 (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?

【问题讨论】:

  • X509HostnameVerifier 用于检查主机名是否与存储在服务器的(不是客户端的)X.509 证书中的名称匹配:hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…您能否检查服务器证书中的主题是否与实际的服务器域匹配。例如。使用网络浏览器:shellhacks.com/…
  • 另一件事是SSLSockerFactory 的使用可能会覆盖您的SSLConfig REST-assured 类中的设置。这是因为仅在未提供 SSLSockerFactory 时才使用来自 SSLConfig 的配置。见:github.com/rest-assured/rest-assured/blob/…
  • @dzieciou 今天我想知道我是否能以某种方式获得实际的服务器证书,哈哈!我会检查...

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


【解决方案1】:

我找到了根据需要自定义 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 参数 - 这会有所不同!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    相关资源
    最近更新 更多