我的任務是使用 RESTAPI 在 java 中建立與 JIRA 的連接。我遇到了 SSL 安全證書錯誤。我已經嘗試了很多次并查看了谷歌,但我沒有找到任何解決我的問題的方法。誰能幫我解決這個錯誤?
APOD.java
package com.jiraconnection;
import com.fasterxml.jackson.annotation.JsonProperty;
public class APOD {
public final String expand;
public final String id;
public final String key;
public final String self;
public APOD(@JsonProperty("expand") String expand,
@JsonProperty("id") String id,
@JsonProperty("key") String key,
@JsonProperty("self") String self) {
this.expand = expand;
this.id = id;
this.key = key;
this.self = self;
}
}
JavaHttpURLConnectionDemo.java
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class JavaHttpURLConnectionDemo {
public static void main(String[] args) throws IOException {
// Create a neat value object to hold the URL
URL url = new URL("https://jira.atlassian.com/rest/api/latest/issue/JRA-9");
// Open a connection(?) on the URL(?) and cast the response(??)
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
// Now it's "open", we can set the request method, headers etc.
connection.setRequestProperty("accept", "application/json");
// This line makes the request
InputStream responseStream = connection.getInputStream();
// Manually converting the response body InputStream to APOD using Jackson
ObjectMapper mapper = new ObjectMapper();
APOD apod = mapper.readValue(responseStream, APOD.class);
// Finally we have the response
System.out.println(apod.expand);
}
}
錯誤
Exception in thread "main" 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:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:324)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:267)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:262)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1340)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1215)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1158)
uj5u.com熱心網友回復:
HttpsURLConnection默認情況下使用 JDK 受信任證書來驗證服務器證書是否已知和受信任。如果它在那里,它不會拋出SSLHandshakeException
Jira 目前有以下證書鏈:

您可以通過在初始化后添加斷點來輕松驗證您是否HttpsURLConnection擁有受信任的證書,HttpsURLConnection請參見下面的示例:

所以我的假設是,在您的情況下,JDK 信任庫中不存在證書。您可以做的是提取 Jira 證書,就像此處所示:使用 openssl 從服務器獲取證書,然后將其匯入cacert此處的檔案中:$JAVA_HOME/lib/security/cacerts. 但我認為為您的 HttpsUrlConnection 提供自定義 ssl 配置會更好,因為我認為它更易于維護。但任何一種選擇都行得通。
因此,以下代碼片段適用于使用自定義信任庫時的選項 2:
選項 2
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.util.Objects;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) throws Exception {
Path trustStorePath = Paths.get("/path/to/your/truststore.jks");
char[] trustStorePassword = "my-password".toCharArray();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
try(InputStream inputStream = Objects.requireNonNull(Files.newInputStream(trustStorePath))) {
trustStore.load(inputStream, trustStorePassword);
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
URL url = new URL("https://jira.atlassian.com/rest/api/latest/issue/JRA-9");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(socketFactory);
connection.setRequestProperty("accept", "application/json");
try(InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String responseBody = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(responseBody);
}
}
}
或者,您可以在沒有來自檔案系統的自定義信任庫的情況下行內執行所有操作,如下所示。通過這種方式,您將根 ca 作為 pem,并以DigiCert High Assurance EV ROOT CA編程方式將其加載到您的記憶體信任庫中。
選項 3
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) throws Exception {
String atlassian = ""
"MIIFdzCCBP6gAwIBAgIQAgzZlKL4HKlpT4RkDXUi8TAKBggqhkjOPQQDAzBWMQsw"
"CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTAwLgYDVQQDEydEaWdp"
"Q2VydCBUTFMgSHlicmlkIEVDQyBTSEEzODQgMjAyMCBDQTEwHhcNMjIwNTEwMDAw"
"MDAwWhcNMjMwNjEwMjM1OTU5WjBuMQswCQYDVQQGEwJBVTEYMBYGA1UECBMPTmV3"
"IFNvdXRoIFdhbGVzMQ8wDQYDVQQHEwZTeWRuZXkxGjAYBgNVBAoTEUF0bGFzc2lh"
"biBQdHkgTHRkMRgwFgYDVQQDDA8qLmF0bGFzc2lhbi5jb20wWTATBgcqhkjOPQIB"
"BggqhkjOPQMBBwNCAAR7p4KtlAjEKMIH66rdbCXtkR5nO20hqZco8B/L EuJ9mqJ"
"PT4dmaDR8OZWzlLXfqiKKhtxuPckC5dtwns4kXyAo4IDlDCCA5AwHwYDVR0jBBgw"
"FoAUCrwIKReMpTlteg7OM8cus 37w3owHQYDVR0OBBYEFMw8XjgJmgk4VGCBWOyG"
"Lr/FMrRZMCkGA1UdEQQiMCCCDyouYXRsYXNzaWFuLmNvbYINYXRsYXNzaWFuLmNv"
"bTAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC"
"MIGbBgNVHR8EgZMwgZAwRqBEoEKGQGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E"
"aWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5jcmwwRqBEoEKGQGh0"
"dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4"
"NDIwMjBDQTEtMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcC"
"ARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGFBggrBgEFBQcBAQR5MHcw"
"JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcw"
"AoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTSHlicmlk"
"RUNDU0hBMzg0MjAyMENBMS0xLmNydDAJBgNVHRMEAjAAMIIBgQYKKwYBBAHWeQIE"
"AgSCAXEEggFtAWsAdwCt9776fP8QyIudPZwePhhqtGcpXc xDCTKhYY069yCigAA"
"AYCt4OEbAAAEAwBIMEYCIQC37AW4L7CCrKn0 kTydWf3zn6tdkFOg/ZI3mUU4/P3"
"CwIhAOnIlT0eX2nzpr6 d3GReTVlVf5 coiyYsSOJWOANM2ZAHcANc8ZG7 xbFe/"
"D61MbULLu7YnICZR6j/hKu oA8M71kwAAAGAreDg7wAABAMASDBGAiEAj67xO2t2"
"OVtwSjLdsD8RknexjRqu Ifwp5wO/2p8a84CIQDw9OKwzRnQ4cxYPKPrIYGm5hbH"
"KfVwcBMmo0u0XQ2YlQB3ALNzdwfhhFD4Y4bWBancEQlKeS2xZwwLh9zwAw55NqWa"
"AAABgK3g4SEAAAQDAEgwRgIhAP/l3SLBl5/9RHQvd5GjApgGAne4J/XnA68l/vQp"
"x7jHAiEAxWnEzde1lf4a1kMuFUyc6fBUE88GVb zC9rjv4KCDcQwCgYIKoZIzj0E"
"AwMDZwAwZAIwFcy1X o/HkXrM8rFdcjBGCieA0oBeRSSifale32U36xquKPBtSvm"
"2g/HAZh2N3DDAjBM4zmAiD0WTA0o3Fnh03mIwP/98RqXvjiDUL/bzovejseo8eRp"
"FDjNl90IcJuAoGc=";
String digicertCa = ""
"MIIEFzCCAv gAwIBAgIQB/LzXIeod6967 lHmTUlvTANBgkqhkiG9w0BAQwFADBh"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD"
"QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaMFYxCzAJBgNVBAYTAlVT"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMDAuBgNVBAMTJ0RpZ2lDZXJ0IFRMUyBI"
"eWJyaWQgRUNDIFNIQTM4NCAyMDIwIENBMTB2MBAGByqGSM49AgEGBSuBBAAiA2IA"
"BMEbxppbmNmkKaDp1AS12 umsmxVwP/tmMZJLwYnUcu/cMEFesOxnYeJuq20ExfJ"
"qLSDyLiQ0cx0NTY8g3KwtdD3ImnI8YDEe0CPz2iHJlw5ifFNkU3aiYvkA8ND5b8v"
"c6OCAYIwggF MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAq8CCkXjKU5"
"bXoOzjPHLrPt 8N6MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4G"
"A1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYI"
"KwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j"
"b20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp"
"Q2VydEdsb2JhbFJvb3RDQS5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny"
"bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAE"
"NjA0MAsGCWCGSAGG/WwCATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgG"
"BmeBDAECAzANBgkqhkiG9w0BAQwFAAOCAQEAR1mBf9QbH7Bx9phdGLqYR5iwfnYr"
"6v8ai6wms0KNMeZK6BnQ79oU59cUkqGS8qcuLa/7Hfb7U7CKP/zYFgrpsC62pQsY"
"kDUmotr2qLcy/JUjS8ZFucTP5Hzu5sn4kL1y45nDHQsFfGqXbbKrAjbYwrwsAZI/"
"BKOLdRHHuSm8EdCGupK8JvllyDfNJvaGEwwEqonleLHBTnm8dqMLUeTF0J5q/hos"
"Vq4GNiejcxwIfZMy0MJEGdqN9A57HSgDKwmKdsp33Id6rHtSJlWncg d0ohP/rEh"
"xRqhqjn1VtvChMQ1H3Dau0bwhr9kAMQ 959GG50jBbl9s08PqUU643QwmA==";
String digicertRootCa = ""
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD"
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB"
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97"
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt"
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz EkIYIvUX7Q6hL hqkpMfT7P"
"T19sdl6gSzeRntwi5m3OFBqOasv zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4"
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX jkMOvJwIDAQABo2MwYTAO"
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR"
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw"
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK t1EnE9SsPTfrgT1eXkIoyQY/Esr"
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg"
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp dWOIrWcBAI 0tKIJF"
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU Krk2U886UAb3LujEV0ls"
"YSEY1QSteDwsOoBrp uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk"
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=";
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
for (String certificateContent : Arrays.asList(atlassian, digicertCa, digicertRootCa)) {
byte[] decodedCertificate = Base64.getDecoder().decode(certificateContent);
try(ByteArrayInputStream certificateAsInputStream = new ByteArrayInputStream(decodedCertificate);
BufferedInputStream bufferedCertificateStream = new BufferedInputStream(certificateAsInputStream)) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(bufferedCertificateStream);
trustStore.setCertificateEntry(UUID.randomUUID().toString(), certificate);
}
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
URL url = new URL("https://jira.atlassian.com/rest/api/latest/issue/JRA-9");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(socketFactory);
connection.setRequestProperty("accept", "application/json");
try(InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String responseBody = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(responseBody);
}
}
}
最后的手段是禁用證書驗證,但我不建議這樣做。下面是一個例子:
選項 4
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.stream.Collectors;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;
public class App {
public static void main(String[] args) throws Exception {
X509ExtendedTrustManager unsafeTrustManager = new X509ExtendedTrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{ unsafeTrustManager }, null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
URL url = new URL("https://jira.atlassian.com/rest/api/latest/issue/JRA-9");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(socketFactory);
connection.setRequestProperty("accept", "application/json");
try(InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String responseBody = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(responseBody);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/475916.html
標籤:爪哇 ssl jira-rest-api
