如何在 Rest-Assured java 中使用证书进行 HTTPS GET 调用

How to make HTTPS GET call with certificate in Rest-Assured java

如何使用 java 中的 Rest-Assured 对需要证书的端点进行 GET 调用。我有 .pem 格式的证书。 PEM 文件中有证书和私钥。

我是新手放心,但是我知道这种使用数字证书进行客户端认证的问题

在放心文档中只有配置证书的选项:JKS

RestAssured.config = RestAssured.newConfig().sslConfig(new SSLConfig("/truststore_javanet.jks", "test1234");

将您的 PEM 转换为 JKS。用 portecle 打开它并确保密码正确,并且您已加载证书并将所有证书链连接到 CA root。 Portecle 使用 GUI 简化了命令行,还允许您创建 JKS

http://portecle.sourceforge.net/

当您的java客户端不信任服务器证书

时,总是会出现此错误
 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

解决此问题的最简单方法是在您的 jdk 密钥库中包含服务器证书链。

首先,下载使用浏览器打开 https 连接的服务器证书,例如 chrome。失败也没关系。单击工具栏中的绿色锁>详细信息>查看服务器证书并下载为 PEM。最好自己下载以确保您使用的是正确的。下载认证链所有证书

然后,使用 portecle 在 JDK_HOME/jre/lib/security 打开 jdk cacerts。密码将为 'changeit'。将服务器证书添加为 'trusted'

现在,PKIX 路径构建失败将消失。如果不是,请检查证书和您正在使用的 JDK

使用以下代码得到它 -

KeyStore keyStore = null;
SSLConfig config = null;

try {
        keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(
                new FileInputStream("certs/client_cert_and_private.p12"),
                password.toCharArray());

    } catch (Exception ex) {
        System.out.println("Error while loading keystore >>>>>>>>>");
        ex.printStackTrace();
    }

    if (keyStore != null) {

        org.apache.http.conn.ssl.SSLSocketFactory clientAuthFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore, password);

        // set the config in rest assured
        config = new SSLConfig().with().sslSocketFactory(clientAuthFactory).and().allowAllHostnames();

RestAssured.config = RestAssured.config().sslConfig(config);
RestAssured.given().when().get("/path").then();

下面提到的代码可以正常工作,

public static void getArtifactsHttps(String args) {
    String username = "username";
    String password1 = "password";
    StringBuilder authorization = new StringBuilder();
    authorization.append(username).append(":").append(password);
    String authHeader = "Basic " + Base64.getEncoder().encodeToString(authorization.toString().getBytes());


    String response = RestAssured
            .given()
            .trustStore("D:\workspace\DemoTrust.jks", "DemoTrustKeyStorePassPhrase")
            .when()
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            .header("Authorization", authHeader)
            .baseUri("https://server.us.oracle.com:55898")
            .queryParam("name", args)
            .get("/validendpoint").prettyPrint();

    System.out.println("RESPONSE" + response);
}

就我而言,使用 "relaxed HTTPs validation" 解决了我的问题:

given().relaxedHTTPSValidation().when().post("https://my_server.com")

使用 RestAssured 3.0,我采用了@rohitkadam19 的代码并让它工作:

@Before
public void setUp() throws Exception {
    try {
        RestAssured.port = port;
        RestAssured.useRelaxedHTTPSValidation();
        RestAssured.config().getSSLConfig().with().keyStore("classpath:keystore.p12", "password");
    } catch (Exception ex) {
        System.out.println("Error while loading keystore >>>>>>>>>");
        ex.printStackTrace();
    }
}

使用 org.apache.http.conn.ssl.SSLSocketFactory 的方法现已弃用。如果您使用的是来自 io 的最新版本 RestAssured,那么最好的方法是使用以下方式设置身份验证:

    RestAssured.authentication =
        RestAssured.certificate(
            "/path/to/truststore",
            "trust store password",
            "/path/to/p12",
            "p12 password",
            CertificateAuthSettings.certAuthSettings());

请注意,CertificateAuthSettings.certAuthSettings() 使用默认 KeyStore 设置,因此请注意这一点。

您需要允许 RestAssured 客户端使用自签名证书。为此,您需要将证书(public 密钥)放入信任库(而非密钥库)。

RestAssured
  .config()
  .sslConfig(
    sslConfig().with().trustStoreType("PKCS12").and()
      .trustStore(ResourceUtils.getFile("classpath:keystore/keystore.p12"), "password"));

//headerMap是header的map 得到

Response response = given().headers(headerMap)
.config(RestAssuredConfig.config().decoderConfig(DecoderConfig.decoderConfig().defaultContentCharset("UTF-8")).and().sslConfig(new SSLConfig().relaxedHTTPSValidation())) .contentType(ContentType.JSON).when().get(url).then().extract().response();

Post

response =   given().headers(headerMap) .config(RestAssuredConfig.config().decoderConfig(DecoderConfig.decoderConfig().defaultContentCharset("UTF-8")).and().sslConfig(new SSLConfig().relaxedHTTPSValidation()))
.contentType(ContentType.JSON).body(body).when().post(url).then().extract().response();

这对我有用,谢谢大家。我正在使用 RestAssured v 3.0,这是针对 Post 但我们可以将其更改为 .get() 并删除 .body(...)

    ResponseSpecification responseSpec = null;
    Response response123 = null;
    
    RestAssured.config = RestAssured.config().sslConfig(
            new SSLConfig().keystore("app trust.jks", password)
                    .keystore("key trust.jks", password));
    
    responseSpec = given()
            .urlEncodingEnabled(Encode url = true or false)
            .body(BodyToPOST)
            .config(RestAssured.config())
            .contentType("application/json")
            .headers(appropriate headers)
            .expect()
            .statusCode(200);
    
    response123 = responseSpec.when()
            .post(url)
            .then()
            .extract()
            .response();

我在 4.3.3 版本的 RestAssured 上几乎没有找到这些答案。

我终于发现了这个:RestAssured.trustStore(truststoreFilePath, password)

用法:

String truststore = Props.getStringProperty("truststore", ""); // truststore in jks format
if (StringUtils.isNotBlank(truststore)) {
    File truststoreFile = new File(truststore);
    if (!truststoreFile .exists()) {
        throw new RuntimeException("Could not initialize the truststore 
 because file specified does not exist: " + truststore);
    }
    String password = Props.getStringProperty("truststorePassword", "changeit");
    RestAssured.trustStore(truststoreFile.getAbsolutePath(), password);
}

现在

RestAssured.given()
    .auth().basic(Props.getStringProperty("user"), Props.getStringProperty("authToken"))
    .with().config(RestAssured.config().connectionConfig(new ConnectionConfig())).when().get("/my-service")

不再有 SSL 握手问题。

要了解该场景,如果您向其发出请求的服务器配置了自签名 SSL 证书,则您必须查看此答案。 Trust SSL证书是在CA(Certificate Authorities)的帮助下由浏览器自动验证的,但是如果是自签名的SSL我们必须给rest client配置truststore(这种情况下请放心)。

什么是信任库?

Truststore 是一种保管库,您可以在其中放置您认为有效的证书,进一步解释,https 验证所涉及的过程类似于以下步骤,

  1. 您向服务器发出请求
  2. 服务器发送证书
  3. 现在客户有责任验证证书,如果它信任 SSL,那么浏览器/http 客户端会联系 CA 来验证证书的真实性,但由于它是自签名 SSL,我们必须配置 http 客户端它应该用于验证证书并且该配置是信任库的配置

现在要完成配置并进行 http 调用,请按照以下步骤操作

  1. 在您的项目中创建一个扩展名为“jks”的truststore文件,创建jks文件时必须配置密码。
  2. 从浏览器下载证书或使用创建的证书(两者相同),证书扩展名通常为“pem”或“crt”
  3. 现在我们需要将证书导入信任库(*.jks 文件),运行 在终端中执行以下命令

keytool -importcert -alias "[[alias for certificate]]" -file [[Certificate name]].pem -keystore [[truststore name]].jks -storepass [[truststore password]]

  1. 现在我们需要配置 请放心,它应该使用这个信任库进行 https 验证

given().config(newConfig().sslConfig(new SSLConfig("/truststore.jks", "truststorepassword")))

我们可以使用上面的实例来执行http get请求, given().config(newConfig().sslConfig(new SSLConfig("/truststore.jks", "truststorepassword"))).get("URL")