簡體   English   中英

OAuth 中的 PKIX 路徑構建失敗 Java 中的身份驗證

[英]PKIX path building failed in OAuth Authentication in Java

我正在嘗試在 discogs 中進行身份驗證:

https://www.discogs.com/developers/#page:authentication,header:authentication-oauth-flow

關於第 2 點:向 DISCOGS 請求令牌 URL 發送 GET 請求,我明白了:

oauth_token=tnMYYwCBsvoecGyBsANXyVKQtICTdDnnzRPeGUfa
oauth_token_secret=xwHpnTRYNJIpdkkTJLMsfXECdHgXeQUrDjzmktPw
oauth_callback_confirmed=true

關於第 3 點:將您的用戶重定向到 DISCOGS 授權頁面,

我創建了這段代碼:

private static void redirectUserToAuthorizePage(String consumerKey) throws IOException {

    String yourUrl = "https://discogs.com/oauth/authorize?oauth_token=" + consumerKey;
    URL url = new URL(yourUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setDoOutput(true);
    conn.setRequestMethod("GET");

    int statusCode = conn.getResponseCode();
    System.out.println("Status Code: " + statusCode);

    conn.disconnect();

}

但我得到了這個錯誤:

但我收到此錯誤:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)

提供的錯誤表明您的應用程序無法與遠程服務器discogs.com建立 SSL 安全通信,因為它無法在配置為信任的服務器中找到該服務器的有效證書。

在后台, HttpURLConnection將使用Java 安全套接字擴展來建立安全的 SSL 通信。

為了解決這個問題,你有幾個選擇,主要是:

  • 使用指向包含服務器證書的密鑰庫和密碼的javax.net.ssl.trustStorejavax.net.ssl.trustStorePassword系統屬性運行您的應用程序。
  • 將服務器證書包含在受信任的默認密鑰庫中,其中之一是:
    • <java-home>/lib/security/jssecacerts
    • <java-home>/lib/security/cacerts

無論選擇何種機制,請確保所需的密鑰庫包含信任遠程服務器所需的所有證書,不僅是 SSL 證書本身,還包括證書鏈中的所有證書。

openssl提供了一個有用的命令,允許您獲取 SSL 連接中使用的所有證書。 在這種情況下,它將提供以下信息,其中包括:

depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
   i:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
-----BEGIN CERTIFICATE-----
MIIDcDCCAligAwIBAgIRALyiewLACTbxSO/mUgPt2z8wDQYJKoZIhvcNAQELBQAw
SzEQMA4GA1UEChMHQWNtZSBDbzE3MDUGA1UEAxMuS3ViZXJuZXRlcyBJbmdyZXNz
IENvbnRyb2xsZXIgRmFrZSBDZXJ0aWZpY2F0ZTAeFw0yMTAzMTYyMjQ5MDVaFw0y
MjAzMTYyMjQ5MDVaMEsxEDAOBgNVBAoTB0FjbWUgQ28xNzA1BgNVBAMTLkt1YmVy
bmV0ZXMgSW5ncmVzcyBDb250cm9sbGVyIEZha2UgQ2VydGlmaWNhdGUwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxBj7SvSJpus5+2s4HLhheJhmKEmcV
MTFIVf3xRDfGpVFeYKAc/o8oB3/OXrqr16kuv2g+bE2d59qVri1uTXX/CRHM6G0E
St/gEdUsGiO1e3VueYGkdgr//s7idEMD0tBHp9ITiR0XUFK75YdWCT6H24fetNzp
bOSMImEeSQsRexKqwcCvM6l4rNshJQ1BVD7NOYPBO9BJuEKU0wCd8yDF20Ig6Qwh
D8B6kRIfNIR1jaQbXGwsvowx4ZHtE4ETd5ftPvKFLfjTMRNFOenJMOeA9te3f2vA
f4jm8furOytI7+sQhZqstxbwPV9OI96rilq4P+ZjP3CW9bfubdyE8ccHAgMBAAGj
TzBNMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMB
Af8EAjAAMBgGA1UdEQQRMA+CDWluZ3Jlc3MubG9jYWwwDQYJKoZIhvcNAQELBQAD
ggEBADFd9W49IsGKTm6WBSsSPLuKn1NFlQmfuRljcZyB01seN7N8fvX4OG/fD+/A
g1nogwDbTl3g1AAyiU6iCKerZevolS2akLdbKwxg/olFRjgwdTN5668Dbz4o3MVY
21AJJ9qO14Oxdu5x+3VhMnsuQdcOzdpwVPmNWIOGQMPD+sOZ8d1hqFp6+3gFQpIL
4kEs2RhjZqwySYoQmBnURx8kbyrs3s/sH06v+CzJwVomf7amOaywJ/VuxmkF9JPp
pxxmlHfbSzlWZGRC4K0ij1+91r6EALVUGgonQGY3FsN2+JTTfg8J9FGqvjb7F+BO
PMPqU/pmCW5h8ej8eyNflagzLFE=
-----END CERTIFICATE-----
---
Server certificate
subject=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
issuer=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
---

在這種情況下,服務器似乎正在使用自簽名證書來標識自己。 您新配置 Java 以信任該證書。

復制並粘貼命令中輸出的證書文本,包括—–BEGIN CERTIFICATE—–—–END CERTIFICATE—– ,並保存到一個新文件,例如discogs.pem

為了在 Java 密鑰庫中導入,應首先將其轉換為 DER 格式。 您也可以使用openssl來做到這一點:

openssl x509 -outform der -in discogs.pem -out discogs.der

然后,將證書導入密鑰庫。 如圖所示,您可以將其導入默認的 JVM kystore 或新的。 讓我們考慮后一種情況並創建一個名為discogs的新密鑰庫:

keytool -import -keystore discogs -file discogs.der

提供您方便的密碼,我們假設changeme為例。

現在,使用上述系統屬性運行應用程序:

java -Djavax.net.ssl.trustStore=discogs \
     -Djavax.net.ssl.trustStorePassword=changeme \
     your.Application

如有必要,為了解決問題,您可以使用具有適當值的javax.net.debug系統屬性allssl

java -Djavax.net.debug=ssl \
     -Djavax.net.ssl.trustStore=discogs \
     -Djavax.net.ssl.trustStorePassword=password \
     your.Application

請考慮查看這個相關的 SO question ,它可能會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM