使用 REST Assured 向不受信任的 SSL 伺服器進行 HTTPS 呼叫
1. 簡介
在本文中,我們將了解如何使用 REST Assured 對 HTTPS 伺服器 URL 進行 HTTPS 呼叫。具體來說,我們將學習如何在系統不信任伺服器 SSL 憑證(例如,由於它是自簽名憑證)的情況下編寫測試。
2. 使用不受信任的 SSL 憑證導致測試失敗
我們可以使用 REST Assured 來呼叫我們的伺服器,如下所示:
given()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
當我們測試非 HTTPS URL 或具有有效 SSL 憑證的 URL 時,這樣的測試將會完美地進行。
但是,如果我們正在測試具有不受信任的 SSL 憑證的 HTTPS URL,REST Assured 將會拋出例外:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378)
... 57 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:388)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:271)
... 123 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:148)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:129)
... 126 more
很多情況下,這是可取的行為。如果我們對一個 SSL 憑證有問題的網站進行測試,通常希望測試失敗。
但是,在某些情況下,我們需要能夠測試此類網站。例如,我們可能正在測試尚未獲得有效證書的應用程式的預發布版本。
3. 放寬 HTTPS 驗證
解決這個問題最簡單的方法是在測試呼叫中啟用寬鬆的 HTTPS 驗證。我們可以在呼叫鏈中加入relaxedHTTPSValidation()
呼叫來實現:
given()
.relaxedHTTPSValidation()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
這是提供已啟用寬鬆驗證的 SSL 設定的簡寫:
given()
.config(config().sslConfig(sslConfig().relaxedHTTPSValidation()))
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
這非常簡單,可能就是我們所需要的全部。但是,我們需要注意,這將接受任何 SSL 憑證用於我們的調用,無論其無效的原因是什麼。這包括不受信任的證書,也包括過期的證書,甚至是為錯誤的網域定義的證書。它還將接受任何網站的任何 SSL 證書,而不僅僅是我們感興趣的網站。
4. 信任證書
與其將客戶端配置為接受任何 SSL 證書,不如為我們的網站提供實際的 SSL 證書。這樣,我們既可以信任該證書,又不會帶來額外的負擔──信任其他證書,並接受無效的證書。
4.1. 建立信任庫
我們需要做的第一件事是建立一個包含適當憑證的 Java Truststore。
首先,我們需要取得證書的副本。我們可以使用openssl
命令列工具直接從伺服器下載:
$ echo -n | openssl s_client -connect self-signed.badssl.com:443
輸出結果除了包含許多其他詳細資訊外,還將包含實際證書。我們可以在「—–BEGIN CERTIFICATE—–」和「—–END CERTIFICATE—–」行之間找到它:
-----BEGIN CERTIFICATE-----
MIIDeTCCAmGgAwIBAgIJAPUiQDKMrnL3MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp
c2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0y
NTA5MDkyMTAwMjZaFw0yNzA5MDkyMTAwMjZaMGIxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQK
DAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2
PmzAS2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMW
hyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3A
xPxTuW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqve
ww9HdFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SY
QCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0T
BAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZI
hvcNAQELBQADggEBACWqo3kJfTMrXjn0w3eUDDUbx18hcvKFGgqkB3V3wnghNJov
WKVaSgkLvWoiDATFZrPIo20cKQ+f0tAMmOvQLo4X5LEPvW+rRJXOLGVPrxlN8Rqc
sOC1oVCATFcXLEHkA0hKdeeh4+GtKavnmYFJuG2OuSW4F1QPLJzFTagn5P1UftR8
ARpYqWhQhncPY+sh2R8Bg+Mqxc+Iu8LlNzUc2P4ZqcmTEhClr9nKzz7ZJGmI61o2
BrX810+j3oZ28VlLvh5TxbD58wkCpF6EW1A+xPZhMoTmRWGvYijTfj6EeiZNg7/N
r42vdJjW11p8FXlJEaIkczUjdxiJsfmZAVqIe5Y=
-----END CERTIFICATE-----
然後,我們需要將其寫入文件,例如badssl.crt
。完成後,我們可以從中建立一個 Java 金鑰庫:
$ keytool -import -trustcacerts -keystore badssl.jks -storepass changeit -noprompt -alias badssl -file badssl.crt
Certificate was added to keystore
這將建立一個名為badssl.jks
的文件,其密碼為changeit
,我們將在badssl.crt
中找到的憑證儲存在其中。
完成此操作後,我們應該驗證金鑰庫以確保其正確性:
$ keytool -list -v -keystore badssl.jks -storepass changeit
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: badssl
Creation date: 12 Sept 2025
Entry type: trustedCertEntry
Owner: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Issuer: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Serial number: f52240328cae72f7
Valid from: Tue Sep 09 22:00:26 BST 2025 until: Thu Sep 09 22:00:26 BST 2027
Certificate fingerprints:
SHA1: 9C:F3:00:1D:37:04:A9:3D:94:0E:24:0D:72:72:4E:F6:1B:D8:86:2E
SHA256: CE:1F:57:5F:E6:4E:D2:D5:18:8B:B4:05:DD:D8:AE:E1:1A:00:18:35:FD:F5:1A:3C:6F:54:CC:43:65:96:C9:54
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
此時,我們已準備好在測試中使用該憑證。
4.2. 每個請求使用信任庫
我們可以設定 REST Assured,使其在單一請求中使用我們的信任庫。具體操作方式與啟用寬鬆 HTTPS 驗證的方式非常相似。我們提供了一個了解信任庫的 SSL 配置:
given()
.config(config().sslConfig(sslConfig().trustStore("/badssl.jks", "changeit")))
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
我們的badssl.jks
檔案需要放在類別路徑上的適當位置, changeit
是我們之前定義的商店密碼。
此時,我們的測試將正確通過此信任庫中的任何證書,但拒絕任何其他無效的證書。
4.3. 全域使用信任庫
我們不需要在每個單獨的請求上配置信任庫,而是可以配置 REST Assured 來全域支援我們的信任庫:
RestAssured.config = RestAssured.config().sslConfig(SSLConfig.sslConfig().trustStore("/badssl.jks", "changeit"));
這與我們之前使用的配置完全相同,但我們正在更新全域配置,而不是在單一請求中指定它。從現在開始,我們發出的所有請求都將知道此信任庫,因此將信任此 SSL 憑證:
given()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
這裡我們沒有執行任何特定操作來信任 SSL 證書,但這次測試會通過。這是因為全域設定已經知道我們的信任庫,因此系統在我們每次呼叫 REST Assured 時都會信任此憑證。
5. 總結
在本文中,我們探討如何設定 REST Assured 以接受不受信任的 SSL 憑證。這使我們能夠測試可能使用自簽名憑證或其他無效憑證的網站。下次您需要測試類似的網站時,不妨嘗試一下。
與往常一樣,本文中的所有範例都可以在 GitHub 上找到。