问题来了

昨天,我还在我的工位上愉快的敲的代码,有位开发组的同事Z给我发消息。

开发组同事Z:大哥,这个PKI的登录功能是你做的吗?

我:是呀!N年前的事了。。。

开发组同事Z:PKI登录功能出问题了!有位客户使用他的PKI登录我们做的系统,登录时报错,换了几台电脑也不行。但是他使用他的PKI能登录其他的系统。能帮忙看一下吗,我找过好多同事看过了,他们看了下,都不知道如何入手

我:报错是报什么错?能具体的描述下吗?

开发组同事Z:访问系统时,能弹出证书的选择框,选择完证书后,Chrome浏览器的报错信息是:ERR_SSL_PROTOCOL_ERROR

我:行吧,我待会过去瞧瞧

问题分析

之前在配置tomcat的SSL时,我已经把客户证书的根证书已经导入到服务器信任证书列表内(配置见附录),“能弹出证书的选择框”说明服务器端是能识别出客户证书,但是为什么在登录的过程中,就报错了,可能有如下的几种原因:

  1. 服务器端的证书和服务器端的信任证书配置有误;(我一直以为是服务器端证书中的IP地址和服务器的IP不一致,后来才发现这个是不可能的)
  2. 登录过程中,tomcat能读取到客户端的证书,在程序处理的过程中,拒绝该证书;(客户端的证书的格式不被服务器端接受)
  3. 客户端证书过期了?(通过上面的描述好像不是这个错误)
  4. tomcat或者JDK有问题?(这个不太可能,其他用户使用PKI能登录呀)

解决问题

博主当时也是有点懵逼,不知道该怎么解决这个问题。好在博主有敢于尝试的精神,决定一个一个试一下。

重新安装服务器端证书

首先使用keytool工具生成服务器端证书,再使用keytool导入客户的根证书到服务器端的信任证书库中。然后把服务器端证书和服务器端的信任证书库放入tomcat,配置、重启tomcat(这里省略了具体的配置过程,具体的配置步骤见附录)。经过一番尝试,发现选择完证书还是报错。又经过一番折腾,还是没有找过是啥原因,正在灰心丧气的时候,灵机一动,程序员不是应该从日志中找错误吗?于是从网上找了一下java中如何开启SSL的日志信息。

日志带来曙光

在tomcat中加入JVM参数: -Djavax.net.debug=SSL,handshake,data,trustmanager,重启tomcat。使用客户的证书重新登录,看到后台打印出了很多的日志信息,浏览了一遍后,发现了如下的异常:

http-nio-8443-exec-4, fatal error: 46: General SSLEngine problem
sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: algorithm constraints check failed
%% Invalidated: [Session-7, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio-8443-exec-4, SEND TLSv1.2 ALERT: fatal, description = certificate_unknown
http-nio-8443-exec-4, WRITE: TLSv1.2 Alert, length = 2
http-nio-8443-exec-4, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: General SSLEngine problem
http-nio-8443-exec-4, called closeOutbound()
http-nio-8443-exec-4, closeOutboundInternal()

拿着这个异常信息java.security.cert.CertPathValidatorException: algorithm constraints check failed去google上搜索了一下,找到了如下的这两个网站上的解决方法:

于是乎,按照上面的描述修改了JDK的配置信息,重启tomcat,使用证书登录,居然能正常登录了。心中暗自高兴了好一会儿,满满的成就感,想不到居然修改了一点配置就解决了......在高兴之余,想着搞清楚这到底是怎么一回事!接下来,容我慢慢道来。

刨根到底

到底是做了什么神奇的操作,就解决这问题了呢!首先找到JDK安装目录下的这个文件:

$JAVA_HOME/jre/lib/security/java.security

然后修改其中的两项配置(为了确保不出报错,把这两项禁用的算法全置为空):

# 处理证书路径时禁用的算法
jdk.certpath.disabledAlgorithms=
# 处理SSL/TLS时禁用的算法
jdk.tls.disabledAlgorithms=

然后重启tomcat就行了。

先看一下禁用的算法的语法,如下:

# 总体的语法
禁用的算法1, 禁用的算法2, 禁用的算法3...
# 禁用的每一项算法语法
算法名称 keySize 操作符 数值值

例如:DSA表示禁用DSA算法,RSA keySize < 2048表示禁用密钥长度小于2048的RSA算法,RSA keySize > 1024, RSA keySize < 2048表示禁用密钥长度大于1024小于2048的RSA算法。

后来,仔细看了一下日志,发现在客户证书的信息有这么一行:

Signature Algorithm: SHA1withRSA, OID = 1.2.***.11***9.1.1.*

Key:  Sun RSA public key, 1023 bits

客户证书的密钥长度居然是1023,而JDK8中为了安全性默认禁用了密钥长度小于2048的算法。最终修改的配置如下:

jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 512

问题就这样解决了,哈哈!!!

总结

有时遇到问题,真的是让人摸不到头脑,这时别着急,把自己能想到的方法先尝试一遍,说不定就能行了呢。遇到问题首先可以借助日志来分析问题(就像上面那样打开JDK的SSL的调试日志的开关),通过日志大概就能定位到时哪里出问题了。在实际的开发中,很多程序猿基本上不会记录日志,稍微好一点的可能会在控制台使用System.out.println(xxxx)输出日志,不习惯使用像log4j这样的日志框架来记录日志。有人会说,出了问题,我可以直接debug呀!你有没想过在生产环境中,你还能用IDE来进行调试吗?

附录

tomcat的SSL配置

编辑conf/server.xml文件加入如下的配置:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.base}/server.ks" keystorePass="123456"
truststoreFile ="${catalina.base}/server_trust.ks"
truststorePass="123456"/>

说明:

  • clientAuth为true表示开启SSL双向认证
  • keystoreFile指定服务器端的证书位置
  • truststoreFile指定服务器端信任证书库

服务器端证书配置

  1. 生成服务器端证书

    keytool -genkeypair -v -alias server -keyalg RSA -validity 3650 -keystore ./server.ks  -storepass 123456 -keypass 123456 -dname "CN=192.168.2.89,OU=zfx,O=zfx,L=gz,ST=gd,C=cn"
  2. 导出服务器端证书

    keytool -exportcert -alias server  -keystore ./server.ks  -file ./server.cer  -storepass 123456
  3. 导入服务器端证书到服务器信任证书列表

    keytool -importcert -alias serverca  -keystore ./server_trust.ks  -file ./server.cer  -storepass 123456
  4. 导入客户根证书到服务器信任证书列表

    keytool -importcert -alias urootca -keystore ./server_trust.ks  -file ./uroot.cer  -storepass 123456

使用如下的命令查看信任的证书信息:

keytool -list -keystore ./server_trust.ks -storepass 123456

Keytool命令常用参数

  • -genkeypair在用户主目录中创建一个默认文件”.keystore”,还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书(在没有指定生成位置的情况下,keystore会存在用户系统默认目录)
  • -alias 产生别名 每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写
  • -keystore 指定密钥库的路径(产生的各类信息将不在.keystore文件中)
  • -keyalg 指定密钥的算法 (如 RSA,DSA,默认值为:DSA)
  • -validity 指定创建的证书有效期多少天(默认 90)
  • -keysize 指定密钥长度 (默认 1024
  • -storepass 指定密钥库的密码(获取keystore信息所需的密码)
  • -keypass 指定别名条目的密码(私钥的密码)
  • -dname 指定证书发行者信息 其中: “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名 称,ST=州或省份名称,C=单位的两字母国家代码”
  • -list 显示密钥库中的证书信息如:keytool -list -v –keystore path/to/keystore -storepass password
  • -v 显示密钥库中的证书详细信息
  • -exportcert 导出指定别名的证书,如:keytool - exportcert -alias theAlias -keystore path/to/keystore -file path/to/keystore/cert -storepass pass
  • -file 参数指定导出到文件的文件名
  • -delete 删除密钥库中某条目 keytool -delete -alias theAlias -keystore path/to/keystore –storepass pass
  • -printcert 控制台打印证书的详细信息,如:keytool -printcert -file path/to/keystore/cert -v
  • -keypasswd 修改密钥库中指定条目口令 keytool -keypasswd -alias theAlias -keypass oldPass -new newPass -storepass keystorePass -keystore path/to/keystore
  • -storepasswd 修改keystore口令 keytool -storepasswd -keystore path/to/keystore -storepass oldPass -new newPass
  • -importcert 将已签名数字证书导入密钥库 keytool -importcert -alias certAlias -keystore path/to/keystore -file path/to/keystore/cert

我是如何解决java.security.cert.CertPathValidatorException异常的的更多相关文章

  1. andorid HTTPS 不需要证书 VolleyEror: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not fou

    1.加证书(这里不说) 2.修改代码 import java.security.KeyManagementException;import java.security.NoSuchAlgorithmE ...

  2. Java_解决java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

    找到 jre/lib/security/java.security 将 jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 ...

  3. 解决 java.security.cert.CertificateException: java.lang.IllegalArgumentException: Invalid input to toASCII:

    使用 okhttp3 ,请求 一个 https 网站报错 , 类似这种 https://test_test.test.com , 百度不到问题 所以我写了这篇 给中文世界贡献一下如何解决 还是要学好英 ...

  4. 在ssm框架测试中解决javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException

    在单元测试发现causeBy:javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException 经发现是db.p ...

  5. JAVA 调用https接口, java.security.cert.CertificateException

    package com.easycare.store.util; import java.security.cert.CertificateException; import java.securit ...

  6. 终极解决方案:java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

    报错信息 javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does ...

  7. java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xxx.xxx.xxx found

    https与http不同的是,https加密,需要验证证书,而http不需要. 在连接的代码中加上: static { disableSslVerification(); } private stat ...

  8. java.security.cert.CertificateException: No subject alternative names present

    背景:在开发一个项目中,要调用一个webservice服务,之前设置的是http协议,项目中采用jdk自带的wsimport工具生成的客户端代码; 后来,需求变更要求兼容https协议的webserv ...

  9. 解決 java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

    找到 jre/lib/security/java.security 将 jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 ...

随机推荐

  1. PB开发境界 多个DW进行update

      多个DW进行update //菜鸟代码dw_1.Update()dw_2.Update()初级代码IF dw_1.Update() = 1 And dw_2.Update() = 1 THEN  ...

  2. Spring+Redis集成+关系型数据库持久化

    本篇文章主要介绍了"Spring+Redis集成+关系型数据库持久化",主要涉及到Spring+Redis集成+关系型数据库持久化方面的内容,对于Spring+Redis集成+关系 ...

  3. spring cloud 入门,看一个微服务框架的「五脏六腑」

    Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...

  4. IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

    1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...

  5. 如何备份/迁移wordpress网站

    暴力方法,完全备份网站目录及数据库,上传到新主机 首先,如果是迁移到其他新主机中,需要将新主机的环境配置好,还有对应网站目录和数据库,这些尽量和旧主机一样的设置 接下来,备份旧主机文件,找到网站目录, ...

  6. system libzip must be upgraded to version >= 0.11

    PHP当前最新版本是PHP7.3,今天在尝试安装的过程中报如下错误: system libzip must be upgraded to version >= 0.11, 根据提示我们可以清楚的 ...

  7. Maven 项目打包出现错误 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin

    今天碰到一个奇怪的问题,就是我在eclipse中使用maven命令:clean package 命令打完包之后,通过FlashFXP将jar包上传到Linux服务器后,由于其他原因,我想要修改下程序重 ...

  8. python2程序移植python3的一些注意事项

    1 queue: python2: import Queue python3: import queue 2 queue size: python2: cache = Queue.Queue(maxs ...

  9. 性能瓶颈之System

    如果Source,Target,Mapping和Session都不存在性能上的瓶颈,则问题可能会出在System 因为Integration Service运行时,它使用了System的资源去运行组件 ...

  10. 《你不知道的JavaScript(上卷)》读书笔记

    第一次尝试用思维导图记笔记,感觉还不错~~~不过还是改不了我读书笔记写成抄书笔记的毛病 =.= 因为开始学JS的时候,一般浏览器就已经支持ES6了,所以比较喜欢使用ES6语法,let,=>等,文 ...