我正在尝试使用Keycloak来保护Java Spring Boot REST服务。其中一部分涉及服务与Keycloak之间的通信,以获取公认的OpenID配置。
当所有内容未加密(通过HTTP)时,一切都正常。但是,当我将SSL证书引入混合中(技术上位于两个服务前面的nginx服务器上),就会出现SSL握手错误。
如果我直接使用浏览器访问REST服务或Keycloak,浏览器不会报告SSL错误。从REST服务器机器到Keycloak机器上使用curl也看起来很好,我曾尝试让nginx强制产生TLS 1.2或1.3响应。
实际REST服务尝试访问Keycloak服务时出现了以下错误:
我已经查看了许多其他答案,例如这个,但似乎无法让服务打印除实际异常之外的任何调试信息。我尝试过以下方法:
我该如何启用调试以找出握手失败的原因?
---- 编辑 ----
成功开启了调试日志记录 - 如下评论所建议,需要添加子类别,例如:
当所有内容未加密(通过HTTP)时,一切都正常。但是,当我将SSL证书引入混合中(技术上位于两个服务前面的nginx服务器上),就会出现SSL握手错误。
如果我直接使用浏览器访问REST服务或Keycloak,浏览器不会报告SSL错误。从REST服务器机器到Keycloak机器上使用curl也看起来很好,我曾尝试让nginx强制产生TLS 1.2或1.3响应。
实际REST服务尝试访问Keycloak服务时出现了以下错误:
2022-03-21 19:30:59.526 WARN 27 --- [nio-8080-exec-3] o.keycloak.adapters.KeycloakDeployment : Failed to load URLs from https://.../auth/realms/MyRealm/.well-known/openid-configuration
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
...
我已经查看了许多其他答案,例如这个,但似乎无法让服务打印除实际异常之外的任何调试信息。我尝试过以下方法:
- 在启动服务器的命令行中添加
-Djavax.net.debug=ssl
- 在应用程序的
main()
函数中添加System.setProperty("javax.net.debug", "ssl");
- 将
logging.level.javax=TRACE
和logging.level.net=TRACE
添加到application.properties中
2022-03-21 19:30:34.219 INFO 27 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-03-21 19:30:34.221 INFO 27 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
接着是错误信息:
2022-03-21 19:30:59.526 WARN 27 --- [nio-8080-exec-3] o.keycloak.adapters.KeycloakDeployment : Failed to load URLs from https://.../auth/realms/MyRealm/.well-known/openid-configuration
我该如何启用调试以找出握手失败的原因?
---- 编辑 ----
成功开启了调试日志记录 - 如下评论所建议,需要添加子类别,例如:
System.setProperty("javax.net.debug", "ssl:handshake");
这会产生大量输出,我不确定其中有多少是有用的:
javax.net.ssl|INFO|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.238 UTC|AlpnExtension.java:182|No available application protocols
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.243 UTC|SSLExtensions.java:260|Ignore, context unavailable extension: application_layer_protocol_negotiation
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.243 UTC|SessionTicketExtension.java:408|Stateless resumption supported
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.244 UTC|SSLExtensions.java:260|Ignore, context unavailable extension: cookie
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.248 UTC|SSLExtensions.java:260|Ignore, context unavailable extension: renegotiation_info
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.248 UTC|PreSharedKeyExtension.java:662|No session to resume.
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.248 UTC|SSLExtensions.java:260|Ignore, context unavailable extension: pre_shared_key
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.250 UTC|ClientHello.java:652|Produced ClientHello handshake message (
"ClientHello": {
"client version" : "TLSv1.2",
"random" : "53 1B D2 D9 42 52 1C 8F E5 B0 E8 6A 88 0D A5 97 ED 22 83 1B CA C1 D4 26 1B 14 59 84 63 3C 99 5B",
"session id" : "4C 90 11 23 81 57 BD B5 AE 68 25 5F 32 E8 75 2B E2 8F A2 85 3A D7 76 4C F9 4C F7 16 5E 7C 02 B0",
"cipher suites" : "[TLS_AES_256_GCM_SHA384(0x1302), TLS_AES_128_GCM_SHA256(0x1301), TLS_CHACHA20_POLY1305_SHA256(0x1303), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256(0xCCAA), TLS_DH
E_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_DHE_RSA_W
ITH_AES_128_CBC_SHA256(0x0067), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_
SHA(0x0032), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_RSA_WITH_AES_
128_CBC_SHA(0x002F), TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",
"compression methods" : "00",
"extensions" : [
"server_name (0)": {
type=host_name (0), value=auth-service.mycompany.com
},
"status_request (5)": {
"certificate status type": ocsp
"OCSP status request": {
"responder_id": <empty>
"request extensions": {
<empty>
}
}
},
"supported_groups (10)": {
"versions": [ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144, ffdhe8192]
},
"ec_point_formats (11)": {
"formats": [uncompressed]
},
"signature_algorithms (13)": {
"signature schemes": [rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, rsa_sha224, dsa
_sha224, rsa_pkcs1_sha1, dsa_sha1]
},
"signature_algorithms_cert (50)": {
"signature schemes": [rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, rsa_sha224, dsa
_sha224, rsa_pkcs1_sha1, dsa_sha1]
},
"status_request_v2 (17)": {
"cert status request": {
"certificate status type": ocsp_multi
"OCSP status request": {
"responder_id": <empty>
"request extensions": {
<empty>
}
}
}
},
"extended_master_secret (23)": {
<empty>
},
"session_ticket (35)": {
<empty>
},
"supported_versions (43)": {
"versions": [TLSv1.3, TLSv1.2]
},
"psk_key_exchange_modes (45)": {
"ke_modes": [psk_dhe_ke]
},
"key_share (51)": {
"client_shares": [
{
"named group": ffdhe2048
"key_exchange": {
0000: 8A B0 45 9E 04 62 D4 52 2F 35 E7 60 03 77 ED 8D ..E..b.R/5.`.w..
...
}
},
]
}
]
}
)
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.252 UTC|Alert.java:238|Received alert message (
"Alert": {
"level" : "fatal",
"description": "handshake_failure"
}
)
javax.net.ssl|ERROR|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.253 UTC|TransportContext.java:361|Fatal (HANDSHAKE_FAILURE): Received fatal alert: handshake_failure (
"throwable" : {
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
...
)
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.253 UTC|SSLSocketImpl.java:1755|close the underlying socket
javax.net.ssl|DEBUG|1C|http-nio-8080-exec-7|2022-03-21 22:37:28.253 UTC|SSLSocketImpl.java:1774|close the SSL connection (initiative)
2022-03-21 22:37:28.255 WARN 26 --- [nio-8080-exec-7] o.keycloak.adapters.KeycloakDeployment : Failed to load URLs from https://auth-service.mycompany.com/auth/realms/MyRealm/.well-known/openid-configuration
ssl
已不足,您必须添加相关的“子类型”,例如ssl:handshake:keymanager
。然而,这种跟踪很少有助于解决除缺少客户端证书之外的警报接收40问题 - 您的nginx是否设置为需要客户端证书?Nginx日志显示了什么? - dave_thompson_085.well-known/openid-configuration
的请求,所以看起来REST服务实际上没有发出调用?或者nginx在握手期间失败时不记录请求。 - DrTeeth[TLS_AES_256_GCM_SHA384(0x1302), TLS_AES_128_GCM_SHA256(0x1301),...
,而服务器有它自己的密码列表:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:...
,它们没有交集。所有客户端密码都以“TLS”开头,而所有服务器密码都以“ECDHE”开头。我从安全建议列表中提取了服务器建议,因此不想更改它们。是否有正确的方法向JDK添加新密码? - DrTeeth