简体   繁体   中英

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

How can I make a GET call using Rest-Assured in java to a endpoint which requires certificate. I have certificate as .pem format. In PEM file there is certificate and private key.

在我的情况下,使用“宽松的 HTTPs 验证”解决了我的问题:

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

Got it working with following code -

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();

I am new to rest-assured but I know this kind of problems using digital certificates for client authentication

In rest-assured doc is only an option to configure certificate: JKS

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

Convert your PEM to JKS. Open it with portecle and ensure that the password is right and you have the certificate loaded and all the certification chain to CA root. Portecle simplify the command-line using a GUI and also allows you to create the JKS

http://portecle.sourceforge.net/

This error occurs ALWAYS when your java client do not trust in server certificate

 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

The easiest way to fix this is include the server certificate chain in your jdk keystore.

First, download the server certificates opening an https connection with your browser, for example with chrome. It does not matter it fails. Click on the green lock in the toolbar>Detail>See server certicate and download as PEM. It is best to download it yourself to make sure you are using the correct. Download all certificates of certification chain在此处输入图片说明

Then, open jdk cacerts at JDK_HOME/jre/lib/security with portecle. Password will be 'changeit'. Add the server certificates as 'trusted'

Now, PKIX path building failed will dissapear. If not, check the certificates and the JDK you are using

Using RestAssured 3.0 I took @rohitkadam19's code and got it working so:

@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();
    }
}

The method using org.apache.http.conn.ssl.SSLSocketFactory is now deprecated. If you are using the latest version of RestAssured from io then the best method is to set your authentication using:

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

Note, CertificateAuthSettings.certAuthSettings() uses default KeyStore settings, so be aware of this.

The code mentioned below just works,

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);
}

You need to allow self-signed certificate for RestAssured client. To do so, you need to place your certificate (public key) to the truststore (not keystore).

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

//headerMap is map of header Get

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();

This worked for me, thank you everyone. I am using RestAssured v 3.0, this is for Post but we can just change that to .get() and removed .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();

I had no luck with pretty much any of these answers on 4.3.3 version of RestAssured.

I finally discovered this: RestAssured.trustStore(truststoreFilePath, password)

Usage:

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);
}

Now

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

Has no more SSL handshake issues.

To understand the scenario, you must be looking into this answer if the server, which you are making a request to, is configured with a self-signed SSL certificate. Trust SSL certificates are automatically validated by the browser with the help of CA(Certificate Authorities), but if it is a self-signed SSL we must configure truststore to the rest client(rest assured in this case).

What is the truststore?

Truststore is kind of vault in which you place certificates which you believe are valid, to explain further, the process involved in https validation is similar to the following steps,

  1. You make request to the server
  2. Server sends a certificate
  3. Now it is clients responsibility to validate the certificate, if it was trust SSL, then browser/ http client approaches CA to validate certificate's authenticity, but since it is self signed SSL, we have to configure the http client that whom it should approach for validating certificate and that configuration is truststore's configuration

Now to complete the configuration and make the http call, follow these steps

  1. Create a truststore file with extension "jks" in your project, have to configure the password while creating the jks file.
  2. Download the certificate from the browser or use the created certificate(both are same), certificate extension is usually "pem" or "crt"
  3. Now we need to import the certificate into the truststore(*.jks file), run the below command in the terminal

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

  1. Now we need to configure Rest assured that it should use this truststore for https validation

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

We could use the above instance to perform http get request, given().config(newConfig().sslConfig(new SSLConfig("/truststore.jks", "truststorepassword"))).get("URL")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM