SSL - SSLHandshakeException: No subject alternative names matching IP address <ip> found

一、异常日志

javax.net.ssl.SSLHandshakeException:
    Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 110.75.244.16 found
        at sun.security.util.HostnameChecker.matchIP(Unknown Source)
	at sun.security.util.HostnameChecker.match(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	... 12 more

二、异常代码

public class SslHandshakeExc_NsanMatchingIp{
	
	public static void main(String[] args) throws Exception {

		URL url = new URL("https://110.75.244.16/gateway.do"); // openapi.alipay.com

		HttpsURLConnection conn = (HttpsURLConnection) 
<think>首先,用户的问题是关于解决一个SSL握手异常:"javax.net.ssl.SSLHandshakeException: No subject alternative names present"。我需要根据系统级指令和用户可见层的要求来回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考站内引用: - 引用[1]: 解释了错误的原因和解决方案。 - 引用[2]: 提供了异常日志和原因。 - 引用[3]: 描述了一个具体场景下的解决。 用户的问题核心是:"我想解决SSL握手异常:没有主体替代名称的错误 请问如何解决 javax.net.ssl.SSLHandshakeException: No subject alternative names present 错误" 我需要构建一个结构清晰的回答: 1. **解释错误原因**:基于引用,错误是因为证书中没有匹配的主机名或IP地址的主题替代名称(Subject Alternative Names, SANs)。 2. **提供解决方案**:列出可能的解决步骤。 3. **生成相关问题**:在回答结束后添加相关问题部分。 4. **添加引用标识**:在引用的段落末尾自然地添加引用标识。 回答结构: - **引言**:简要介绍错误。 - **错误原因**:详细解释。 - **解决方案步骤**:逐步指导如何解决。 - **示例或代码**:如果需要,提供代码示例(如Java代码)。 - **总结**:简要总结。 - **相关问题**:生成相关问题。 确保使用中文回答。 生成相关问题: - 基于主题,生成几个相关问题,例如: 1. 如何检查SSL证书的SANs? 2. 在Java中如何忽略SSL证书验证? 3. 什么是主题替代名称(SANs)? 4. 如何为自签名证书添加SANs? 现在,构建回答内容。 ### 错误原因 根据引用[1]和[2],错误是由于服务器证书中没有包含与请求的主机名或IP地址匹配的主题替代名称(SANs)。在SSL/TLS握手过程中,客户端会验证服务器证书中的主机名是否匹配请求的URL。如果证书只包含Common Name (CN) 而没有SANs,或者SANs中没有匹配的条目,就会抛出此异常[^1][^2]。 ### 解决方案 1. **检查服务器证书**: - 确保服务器证书包含正确的SANs条目。使用工具如OpenSSL检查证书: ``` openssl x509 -in certificate.crt -text -noout ``` 查找"Subject Alternative Name"部分。 2. **更新证书**: - 如果证书缺少SANs,重新生成证书并添加所有可能的IP地址或域名作为SANs。 3. **忽略证书验证(仅用于测试)**: - 在开发环境中,可以临时忽略证书验证。在Java中,创建一个自定义的TrustManager: ```java import javax.net.ssl.*; import java.security.cert.X509Certificate; public class SSLUtil { public static void disableCertificateValidation() { try { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); } catch (Exception e) { e.printStackTrace(); } } } ``` 在代码中调用`SSLUtil.disableCertificateValidation()`来忽略验证[^3]。 4. **使用IP地址作为主机名**: - 如果使用IP地址访问,确保证书的SANs中包含该IP地址。 5. **配置主机名验证**: - 在Java应用中,设置系统属性来禁用严格的主机名验证(不推荐用于生产): ``` System.setProperty("jsse.enableSNIExtension", "false"); ``` 但这可能不适用于所有情况。 ### 总结 此错误通常由于证书配置问题引起。在生产环境中,应正确配置证书SANs;在测试中,可临时忽略验证[^1][^2][^3]。 ### 相关问题 1. 如何为自签名证书添加主题替代名称(SANs)? 2. 在Java中如何安全地处理SSL证书验证? 3. 什么是SSL/TLS握手过程? 4. 如何调试其他常见的SSL握手异常? 确保引用标识自然地添加在引用段落末尾。</think>### SSL握手异常:No subject alternative names present 解决方案 当您遇到 `javax.net.ssl.SSLHandshakeException: No subject alternative names present` 错误时,这表示客户端在SSL/TLS握手过程中无法验证服务器证书的主机名或IP地址。服务器证书缺少匹配请求URL的 **主题替代名称(Subject Alternative Names, SANs)**,导致身份验证失败[^1][^2]。以下是结构化解决方案,帮助您逐步排查和修复问题。 --- ### 一、错误原因详解 - **核心问题**:服务器证书未包含与请求主机名(域名或IP地址)匹配的SANs条目。例如,证书可能只配置了Common Name (CN) 如 `example.com`,但未添加 `192.168.1.1` 等IP地址作为SANs[^1][^2]。 - **触发场景**: - 使用IP地址访问HTTPS服务(如 `https://192.168.1.1`),但证书SANs中未包含该IP- 证书未正确配置SANs扩展(常见于自签名证书或旧证书)。 - Java应用严格验证主机名,而SANs缺失或未更新[^2][^3]。 --- ### 二、解决方案步骤 #### 步骤1:检查服务器证书的SANs 使用OpenSSL工具验证证书内容: ```bash openssl x509 -in server.crt -text -noout | grep "Subject Alternative Name" ``` - **预期输出**:应显示包含IP地址或域名的条目,如 `DNS:example.com, IP:192.168.1.1`。 - **问题处理**:如果输出为空或缺少所需条目,需重新生成证书(见步骤2)[^1]。 #### 步骤2:重新生成证书并添加SANs 生成新证书时,显式添加SANs扩展: 1. 创建配置文件 `san.cnf`: ```ini [req] distinguished_name = req_distinguished_name req_extensions = v3_req [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = example.com # 替换为您的域名 IP.1 = 192.168.1.1 # 替换为您的IP地址 ``` 2. 生成证书: ```bash openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout server.key -out server.crt \ -config san.cnf -extensions v3_req ``` 3. 将新证书部署到服务器(如Tomcat或Nginx)并重启服务[^1]。 #### 步骤3:临时解决方案(仅限测试环境) 在开发或测试中,可临时绕过验证。**注意:生产环境禁用此方法**,因会降低安全性[^3]。 - **Java代码示例**:自定义TrustManager忽略证书验证 ```java import javax.net.ssl.*; import java.security.cert.X509Certificate; public class SSLUtil { public static void disableCertificateValidation() { try { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // 禁用主机名验证 HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); } catch (Exception e) { e.printStackTrace(); } } } ``` - 在发起HTTPS请求前调用:`SSLUtil.disableCertificateValidation();` - **JVM参数调整**(不推荐): ```bash java -Djsse.enableSNIExtension=false -jar your_app.jar ``` #### 步骤4:验证修复 - 使用工具测试连接: ```bash openssl s_client -connect your_server:443 -servername your_domain ``` - 检查输出中是否包含 `subjectAltName` 条目且匹配请求地址。 --- ### 三、总结 - **根本修复**:更新服务器证书,确保SANs包含所有访问方式(域名和IP地址)[^1][^2]。 - **临时方案**:仅在测试环境使用自定义TrustManager,生产环境必须配置有效证书[^3]。 - **最佳实践**:定期检查证书有效期和SANs配置,避免因证书过期或配置错误导致握手失败。 --- ### 相关问题 1. 如何为自签名证书添加主题替代名称(SANs)? 2. 在Java应用中如何安全地处理SSL证书验证(避免禁用验证)? 3. 什么是SSL/TLS握手过程,常见错误有哪些? 4. 如何调试其他SSL异常(如 `certificate_unknown` 或 `handshake_failure`)? [^1]: 引用自SSL异常解析文档,强调SANs缺失是核心原因。 [^2]: 基于异常日志分析,主机名验证失败触发错误。 [^3]: 临时忽略证书的方案适用于开发测试,但需谨慎使用。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值