我正在开发一个Java应用程序(restEasy独立应用程序使用java -jar运行,因此没有容器,只有jdk 8),它是外部Web服务的客户端,我制作了另一个应用程序,这是我的客户端在码头上的示例Web服务。它们都在本地或在我的PC(MYPC_NAME.mycomp.net)上运行
(这是一个问题的解决方案,我需要理解为什么我需要这样解决;它也将帮助任何有相同错误的人)
我为它们两个都生成了密钥库证书和信任库。
keytool -genkey -alias serverkey -storetype jks -keyalg RSA -keysize 2048 -keystore myapprestws.keystore -validity 730 -storepass "MYAPPS Private Keys" -dname "CN=mycomp.net, OU=BANK, O=clientws, L=City, ST=State, C=Country" -keypass "MYAPPS Keys"
keytool -genkey -alias clientkey -keystore myappwsclient.keystore -storepass "MYAPPS Private Keys" -dname "CN=mycomp.net, OU=SHARES, O=myapp, L=City, ST=State, C=Country" -keyalg RSA -keysize 2048 -storetype jks -validity 7 -keypass "MYAPPS Keys"
我试图从我的独立Java应用程序中调用Web服务:https://localhost:8843/myapp/orders
起初我两面都出错 在客户端说
Invalid certificate on target
在服务器端处于调试模式时,它说
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
要解决,我先将两个证书添加到JDK的cacert中(因为我的证书是自签名的),首先是客户端证书,然后是服务器证书
我试图调用网络服务:https://localhost:8843/myapp/orders
它在客户端显示为另一个错误:
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <localhost> doesn't match any of the subject alternative names: []
我使用SAN mycomp.net重新生成了证书,因此我的域mycomp.net上的任何PC都可以使用此证书(SAN未使用* .mycomp.net)
keytool -genkey -alias serverkey -storetype jks -keyalg RSA -keysize 2048 -keystore myapprestws.keystore -validity 730 -storepass "MYAPPS Private Keys" -dname "CN=myapp.net, OU=BANK, O=clientws, L=City, ST=State, C=Country" -keypass "MYAPPS Private Keys" -ext SAN=dns:mycomp.net
keytool -genkey -alias clientkey -keystore myappwsclient.keystore -storepass "MYAPPS Private Keys" -dname "CN=myapp.net, OU=SHARES, O=myapp, L=City, ST=State, C=Country" -keyalg RSA -keysize 2048 -storetype jks -validity 7 -keypass "MYAPPS Private Keys" -ext SAN=dns:mycomp.net
并在删除之前的证书后将其添加到JDK的cacert(因为它们是自签名的)
我认为它需要一个主机名,所以我将URL更改为 https://MYPC_NAME.mycomp.net:8843/myapp/orders
它前进到另一个错误:
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <MYPC_NAME.mycomp.net> doesn't match any of the subject alternative names: [mycomp.net]
所以我重新生成了证书
keytool -genkey -alias serverkey -storetype jks -keyalg RSA -keysize 2048 -keystore myapprestws.keystore -validity 730 -storepass "MYAPPS Private Keys" -dname "CN=myapp.net, OU=BANK, O=clientws, L=City, ST=State, C=Country" -keypass "MYAPPS Private Keys" -ext SAN=dns:MYPC_NAME.mycomp.net
keytool -genkey -alias clientkey -keystore myappwsclient.keystore -storepass "MYAPPS Private Keys" -dname "CN=myapp.net, OU=SHARES, O=myapp, L=City, ST=State, C=Country" -keyalg RSA -keysize 2048 -storetype jks -validity 7 -keypass "MYAPPS Private Keys" -ext SAN=dns:MYPC_NAME.mycomp.net
并在删除之前的证书后将其添加到JDK的cacert(因为它们是自签名的)
然后我点击了网址https://MYPC_NAME.comp.net:8843/myapp/orders,它成功了
我对这个解决方案的问题(或牛肉)。
为什么我需要添加SAN?...我以前曾使用过证书,而以前却不需要此SAN东西,所以我使用了我在-ext上发布的第一个keytool命令,并且该命令已经起作用。 JDK 8现在对keytool强制执行此命令吗?
如果我想使用已经生成并可以在其他应用程序上使用的旧证书怎么办?
此外,SAN现在非常非常具体。您可以在-ext SAN中定义一个IP:ip:XXX.XXX.XXX.XXX或其他名称。但是此证书仅在具有dns的计算机上有效:MYPC_NAME.mycomp.net。此证书不再可移植到其他计算机,我无法随构建一起提供。以前,CN = localhost或CN = *。mycomp.net就足够了。
我的解决方案是否正确(仅仅是因为它有效,并不意味着它是正确的方法吗?)
作为我的其余客户端需要交谈的实际外部Web服务的开发人员的客户端尚未定义SAN及其证书。