weblogic SSL证书错误 FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificat

本文介绍了在项目中遇到Weblogic服务器因SSL证书问题导致的FATAL Alert:BAD_CERTIFICATE错误。尝试通过设置-DUseSunHttpHandler=true解决,但在测试环境仍报错。最终通过修改代码,使httpURLConnection信任所有证书,成功解决问题。

 最近项目需求需要获取Cyberark密码需要通过https协议获取,将代码写完之后,weblogic提示如下错误: FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificat.

随后在网上查阅相关资料,修改Weblogic配置文件setDomainEnv.cmd,增加一段代码: -DUseSunHttpHandler=true。本地环境正常启动,部署到测试环境,启动报错,同一个错误。原因是部署环境的setDomainEnv.cmd没有设置UseSunHttpHandler为true。联系部署同事,告知不能随意修改部署环境上Weblogic文件。

继续百度。,尝试之,修改代码解决之。需要将调用的httpUrlConnction信任所有证书。代码如下: 

	private static String getPasswordByHttps(String object) {
		if (object == null) {
			logger.info("object is required...");
			return null;
		}

		try {
			Map<String, Object> param = new HashMap<String, Object>();
			param.put(SecurityConstants.APP_ID, PptPropsUtils
					.getValueFromProperties(SecurityConstants.APPID));
			param.put(SecurityConstants.SAFE, PptPropsUtils
					.getValueFromProperties(SecurityConstants.SAFE));
			param.put(SecurityConstants.FOLDER, PptPropsUtils
					.getValueFromProperties(SecurityConstants.FOLDER));
			param.put(SecurityConstants.OBJECT, object);
			param.put(SecurityConstants.REASON,
					"get password"); // Reason可随意
		
			java.net.URL postURL = new java.net.URL(
					null,
					PptPropsUtils
							.getValueFromProperties(SecurityConstants.PIDMS_CCP_URL),
					new sun.net.www.protocol.https.Handler());

			HttpURLConnection connection = (HttpURLConnection) postURL
					.openConnection();

			trustAllCertificates(connection); // 信任所有证书

			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("POST");
			connection.setUseCaches(false);
			connection.setRequestProperty("Content-Type", "application/json");
			connection.connect();
			DataOutputStream out = new DataOutputStream(
					connection.getOutputStream());
			out.writeBytes(JSONObject.toJSONString(param));
			out.flush();
			out.close();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), "utf-8"));
			StringBuilder sb2 = new StringBuilder();
			for (String line = reader.readLine(); line != null; line = reader
					.readLine()) {
				sb2.append(line);
			}
			Map<String, Object> result = (Map<String, Object>) JSONObject
					.parse(sb2.toString());
			
			// 成功获取密码
			if (result != null && "200".equals(result.get("code"))) {
				String password = SecurityUtil
						.decrypt(
								(String) result.get(SecurityConstants.PASSWORD),'1111')
								
				
				return password;
			} else
				return null;
		} catch (Exception e) {
			logger.error("异常为: " + e);
			return null;
		}
	}

	// 信任所有证书
	private static void trustAllCertificates(HttpURLConnection con)
			throws NoSuchAlgorithmException, KeyManagementException {

		((HttpsURLConnection) con).setHostnameVerifier(new HostnameVerifier() {
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		});
		// Ignore Certification
		TrustManager ignoreCertificationTrustManger = new X509TrustManager() {

			public void checkClientTrusted(X509Certificate certificates[],
					String authType) throws CertificateException {

			}

			public void checkServerTrusted(X509Certificate[] ax509certificate,
					String s) throws CertificateException {

			}

			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}

		};
		// Prepare SSL Context
		TrustManager[] tm = { ignoreCertificationTrustManger };
		SSLContext sslContext = SSLContext.getInstance("SSL");
		sslContext.init(null, tm, new java.security.SecureRandom());

		// 从上述SSLContext对象中得到SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		((HttpsURLConnection) con).setSSLSocketFactory(ssf);

	}




<think>我们正在讨论TLS/SSL协议中的警报消息(Alert Message),特别是编号为48的消息。根据用户提供的引用和上下文,我们需要解释这个警报的含义、可能的原因以及解决方法。 根据TLS协议规范,警报消息用于在通信过程中通知对端某些错误或异常情况。每个警报消息都有一个特定的编号和描述。然而,用户提供的引用中并没有直接提到编号为48的警报消息。因此,我们需要依靠TLS协议的标准知识。 在TLS协议中,警报消息由两个字节组成:第一个字节表示警报的严重程度(1表示警告,2表示致命错误),第二个字节表示具体的警报类型。编号48(十进制)对应的十六进制是0x30,在TLS警报类型中,0x30对应的警报是`bad_certificate`(错误证书)。 但是,请注意,TLS警报代码的编号可能因协议版本和实现而有所不同,但通常都是按照标准定义的。根据RFC 5246(TLS 1.2)和RFC 8446(TLS 1.3),警报类型定义如下: - 在TLS 1.2中,警报类型`bad_certificate`的值为42(十进制),但请注意,这个值在TLS 1.0和TLS 1.1中是42,在TLS 1.2和1.3中也是42(十进制)?实际上,警报类型是枚举值,通常用0-255的数字表示。但是,我们查一下标准: 实际上,在TLS 1.2(RFC 5246)中,`bad_certificate`的警报代码是42(十进制),而在TLS 1.3(RFC 8446)中,警报代码被重新定义,但`bad_certificate`仍然存在,其值也是42(十进制)吗? 然而,用户提到的是48。我们注意到在引用[5]中提到了一个错误:“FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificat.”。这里就是BAD_CERTIFICATE,但它并没有提到48这个数字。 因此,我们需要确认:在TLS协议中,警报消息的第二个字节(即具体类型)为48(十进制)对应的是什么? 查阅TLS警报类型列表,常见的警报类型有: - 0: close_notify - 10: unexpected_message - 20: bad_record_mac - 21: decryption_failed - 22: record_overflow - 30: decompression_failure - 40: handshake_failure - 42: bad_certificate - 43: unsupported_certificate - 44: certificate_revoked - 45: certificate_expired - 46: certificate_unknown - 47: illegal_parameter - 48: unknown_ca - 49: access_denied - 50: decode_error - ... 等等 根据这个列表,48(十进制)对应的警报类型是`unknown_ca`(未知的证书颁发机构)。 因此,警报消息48(十进制)表示:`unknown_ca`,即接收方不信任发送方证书的颁发机构(CA)。 ### 警报消息48的含义 - **名称**:`unknown_ca`(未知的证书颁发机构) - **严重程度**:通常是致命的(Fatal),导致连接立即终止。 - **含义**:在TLS握手过程中,客户端或服务器收到了对方的证书,但无法验证该证书,因为证书链中的某个证书(通常是根证书或中间CA证书)不在自己的信任存储中。也就是说,接收方不信任对方证书的颁发机构。 ### 可能的原因 1. **自签名证书**:对方使用了自签名证书(即没有受信任的CA签发的证书),而接收方没有将该自签名证书添加到信任库中。 2. **中间CA证书缺失**:对方提供的证书链不完整,缺少中间CA证书,导致接收方无法构建完整的信任链。 3. **根证书不在信任库**:对方证书的根CA不在接收方的信任库中(例如,使用私有CA签发的证书,而接收方没有安装该私有CA的根证书)。 4. **证书过期**:虽然证书过期通常对应警报45(certificate_expired),但有时也可能导致信任链验证失败。 5. **客户端证书验证**:如果服务器要求客户端证书,而客户端提供的证书的CA不被服务器信任,则服务器会发送此警报。 ### 解决方法 根据引用[2]和[5]中的信息,我们可以总结以下解决方法: 1. **将证书添加到信任库**: - 如果使用自签名证书或私有CA签发的证书,需要将根证书(或自签名证书本身)添加到客户端的信任库中(如Java的cacerts,或操作系统的信任存储)。 - 在Java中,可以使用`keytool`导入证书到信任库: ```bash keytool -import -alias mycert -file server.crt -keystore cacerts ``` 2. **配置客户端跳过证书验证(仅测试环境)**: - 在某些情况下,为了测试方便,可以配置客户端跳过证书验证(不推荐生产环境)。例如,在JDBC连接字符串中,可以设置`verifyServerCertificate=false`(参考引用[2])。 - 但是,这样会降低安全性,应仅在开发和测试阶段使用。 3. **确保证书链完整**: - 服务器在配置SSL/TLS时,应该提供完整的证书链(包括所有中间CA证书)。例如,在Nginx中,需要将服务器证书和中间CA证书合并到一个文件中(顺序:服务器证书在前,然后是中间CA证书)。 - 使用OpenSSL命令检查证书链: ```bash openssl s_client -connect example.com:443 -showcerts ``` 4. **检查证书是否有效**: - 确保证书没有过期,且域名匹配(如果证书用于服务器)。 5. **在客户端中明确指定信任的证书**: - 如果使用自定义的信任库,确保在客户端代码中指定信任库的位置和密码。 ### 引用[5]中的错误分析 引用[5]提到错误:“FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificat.”。虽然这里写的是BAD_CERTIFICATE(警报42),但实际可能包括多种证书问题,包括证书格式错误、损坏、无法解析等。而警报48(unknown_ca)是其中一种情况,即CA未知。 ### 结论 - **TLS警报48**:表示未知的证书颁发机构(`unknown_ca`)。 - **解决方案**:将对方证书的根CA添加到信任库,或确保证书链完整。 ### 相关问题 1. 如何将自签名证书添加到Java信任库? 2. 如何生成完整的证书链? 3. 在TLS/SSL握手过程中,还有哪些常见的警报消息? 4. 如何配置Weblogic信任自签名证书? 5. 如何检查SSL证书链是否完整?</think>### TLS/SSL 警报消息 48:`unknown_ca`(未知证书颁发机构) 在 TLS/SSL 协议中,**警报消息 48** 表示 **`unknown_ca`**(未知证书颁发机构)。这是证书验证失败时触发的致命错误Fatal Alert),会导致连接立即终止。以下是详细分析和解决方案: --- ### 根本原因 当客户端或服务器收到对端的证书时,会验证证书链的信任关系。若出现以下情况,会触发警报 48: 1. **证书链不完整** - 缺少中间 CA 证书,导致根 CA 无法被识别(如仅提供终端证书,未包含中间 CA 证书)。 2. **信任库缺失根 CA 证书** - 接收方(客户端或服务器)的信任库(Trust Store)中未安装对方证书链的根 CA 证书。 3. **自签名证书未受信任** - 使用自签名证书(如引用[4]生成的证书)但未将其添加到信任库。 4. **私有 CA 未被信任** - 使用私有 PKI 签发的证书,但接收方未配置信任该 CA。 --- ### 解决方案 #### 方法 1:补充完整证书链(推荐) 确保服务端发送的证书包含完整的证书链(终端证书 + 中间 CA 证书 + 根 CA 证书): ```bash # 合并证书链(顺序:终端证书 → 中间 CA → 根 CA) cat server.crt intermediate.crt root.crt > full_chain.crt ``` 在服务端配置中使用 `full_chain.crt`(如 Nginx/Apache/Tomcat 的 SSL 配置)。 #### 方法 2:将根 CA 添加到信任库 **Java 应用示例**(适用于引用[2][5]的 JDBC/WebLogic 场景): ```bash # 将根 CA 证书导入 Java 信任库 (cacerts) keytool -import -trustcacerts -alias my_root_ca -file root.crt -keystore $JAVA_HOME/lib/security/cacerts ``` 输入默认密码 `changeit`,重启应用。 #### 方法 3:配置客户端信任自签名证书(仅测试环境) - **JDBC 连接**(引用[2]): 添加参数 `verifyServerCertificate=false`(不推荐生产环境): ```bash jdbc:mysql://host:3306/db?verifyServerCertificate=false&useSSL=true ``` - **WebLogic 配置**(引用[5]): 在 `WebLogic Console → Environment → Servers → SSL` 中启用 `Custom Identity and Custom Trust`,并导入证书。 #### 方法 4:检查证书有效性 验证证书是否损坏或格式错误: ```bash # 检查证书内容 openssl x509 -in server.crt -text -noout ``` 若输出包含错误(如 `unable to load certificate`),需重新生成证书(参考引用[4])。 --- ### 警报 48 与其他证书错误的区别 | 警报代码 | 名称 | 原因 | |----------|-----------------------|----------------------------------------------------------------------| | **48** | `unknown_ca` | 根 CA 不被信任或证书链不完整 | | 42 | `bad_certificate` | 证书格式错误、签名无效或密钥不匹配(引用[5]中的错误) | | 43 | `unsupported_certificate` | 证书类型不被支持(如 ECC 证书在仅支持 RSA 的环境中) | | 45 | `certificate_expired` | 证书已过期 | --- ### 预防措施 1. **始终提供完整证书链** 使用工具检查证书链完整性: ```bash openssl s_client -connect example.com:443 -showcerts ``` 2. **同步更新信任库** 当 CA 证书过期或轮换时,及时更新所有客户端的信任库。 3. **生产环境避免自签名证书** 使用 Let's Encrypt 或商业 CA 签发的证书(如 DigiCert/Sectigo)。 4. **配置 TLS 严格验证** 如 ClickHouse 的 `sslmode=verify_full`(引用[3]),而非 `verify_once`。 --- ### 相关问题 1. 如何修复 TLS 警报消息 42 (`bad_certificate`)? 2. 在 Java 中如何动态加载信任库证书? 3. 如何检测 SSL/TLS 握手过程中的证书链问题? 4. Let's Encrypt 证书如何配置完整的证书链? 5. 为什么 TLS 1.3 比 TLS 1.2 在证书验证上更安全(参考引用[1])? [^1]: [^2]: [^3]: [^4]: [^5]:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值