为什么我的 Rest Assured POST 方法不能接受所有主机?
Why can't I accept all hosts for my Rest Assured POST method?
- 我们的目标服务器 (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() 无效。因此,我尝试编写代码:
我的测试class:
...
.given().spec(reqSpec)
...
我的配置class:
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?
- 此外,我知道以下内容,但不知道如何将其用于我的 Rest Assured 连接:https://tutoref.com/how-to-disable-ssl-certificat-validation-in-java/
我找到了根据需要自定义 SSL 配置的方法。
附加了略有审查的代码。查找 "holy grail" 评论:
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 参数 - 这造成了不同!
- 我们的目标服务器 (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() 无效。因此,我尝试编写代码:
我的测试class:
...
.given().spec(reqSpec)
...
我的配置class:
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?
- 此外,我知道以下内容,但不知道如何将其用于我的 Rest Assured 连接:https://tutoref.com/how-to-disable-ssl-certificat-validation-in-java/
我找到了根据需要自定义 SSL 配置的方法。 附加了略有审查的代码。查找 "holy grail" 评论:
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 参数 - 这造成了不同!