与Tomcat 7的相互身份validation

我正在尝试设置在Tomcat 7中运行的Java Web服务以使用相互(双向)身份validation。 似乎无论我做什么,连接到安全端口上的服务都无法正常工作。

这是我创建证书和密钥库等所做的:

//create the key and certificate for the tomcat server. keytool -genkey -v -alias tomcat -keyalg RSA -validity 3650 -keystore tomcat.keystore //create the key and certificate for the client machine. keytool -genkey -v -alias clientkey -keyalg RSA -storetype PKCS12 -keystore client.p12 //export the client key keytool -export -alias clientkey -keystore client.p12 -storetype PKCS12 -rfc -file client.cer //import the client key into the server keystore keytool -import -v -file client.cer -keystore tomcat.keystore 

这是server.xml文件中的连接器:

  

tomcat-users.xml文件如下所示:

       

启动时设置以下内容:

 -Djavax.net.ssl.keyStoreType=jks -Djavax.net.ssl.keyStore=tomcat.keystore -Djavax.net.ssl.keyStorePassword=tomcat -Djavax.net.ssl.trustStore=tomcat.keystore -Djavax.net.ssl.trustStorePassword=tomcat -Djavax.net.debug=SSL 

最后,我将client.p12文件复制到我的客户端计算机,并将其导入Firefox的客户端证书。

第一个问题:当我从Firefox上点击我的服务端点(例如 – https://my.server.com:8443/test )时,我收到响应“安全连接失败”。 SSL收到的记录超过了允许的最大长度。 (错误代码:ssl_error_rx_record_too_long)

第二个问题:我真的不想在端口8443上运行此连接器。我想在端口7800上运行它(这是我们公司的HTTPS标准)。 当我将连接器上的端口更改为7800并尝试命中端点(例如 – https://my.server.com:7800/test )时,它永远不会解析页面。

所以,在某个地方,我显然错过了一个关键的部分。 谁能看到我的错误?

更新:在@Dave G的反馈之后

运行命令:

 openssl s_client -connect localhost:8443 -showcerts 

产生以下输出:

 CONNECTED(00000003) 140642290976584:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 263 bytes --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE --- 

我还在启动时添加了-Djavax.net.debug = SSL。 这会在catalina.out文件的开头生成以下内容:

 trustStore is: tomcat.keystore trustStore type is : jks trustStore provider is : init truststore adding as trusted cert: Subject: CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US Issuer: CN=localhost, OU=unit, O=org, L=Springfield, ST=MO, C=US Algorithm: RSA; Serial number: 0x5485b5a5 Valid from Mon Dec 08 14:28:53 UTC 2014 until Thu Dec 05 14:28:53 UTC 2024 adding as trusted cert: Subject: CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US Issuer: CN=William Jackson, OU=unit, O=org, L=Springfield, ST=MO, C=US Algorithm: RSA; Serial number: 0x5485b6af Valid from Mon Dec 08 14:33:19 UTC 2014 until Sun Mar 08 14:33:19 UTC 2015 trigger seeding of SecureRandom done seeding SecureRandom 

然后有很多:

 Ignoring unavailable cipher suite:  Ignoring unsupported cipher suite:  

好的 – 在挖掘了更多之后,我终于得到了这个工作。 非常感谢@Dave G和本教程: http ://java-notes.com/index.php/two-way-ssl-on-tomcat,其中大部分说明都是转述的。

通常,获得相互身份validationfunction的步骤如下:

  1. 为tomcat服务器创建证书。 客户必须信任此证书。
  2. 为tomcat服务器创建密钥库,并将服务器证书导入其中。
  3. 为客户端创建证书。 服务器必须信任此证书。
  4. 客户端证书导入服务器密钥库
  5. 使用正确的Connector XML更新tomcat server.xml文件。

上述步骤在服务器上是必需的。 完成后,要设置客户端,请执行以下操作:

  1. 将客户端证书从服务器复制到客户端。
  2. 与服务器通信时使用客户端证书(此过程因客户端应用程序的性质而异)。

对于证书配置,我在服务器计算机上执行了以下操作:

 # For the following commands, set the values in parenthesis to be whatever makes sense for your environment. The parenthesis are not necessary for the command. # This is an all-in-one command that generates a certificate for the server and places it in a keystore file, while setting both the certifcate password and the keystore password. # The net result is a file called "tomcat.keystore". keytool -genkeypair -alias (serveralias) -keyalg RSA -dname "CN=(server-fqdn),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keystore tomcat.keystore -keypass (password) -storepass (password) # This is the all-in-one command that generates the certificate for the client and places it in a keystore file, while setting both the certificate password and the keystore password. # The net result is a file called "client.keystore" keytool -genkeypair -alias (clientalias) -keyalg RSA -dname "CN=(client),OU=(organizationalunit),O=(organization),L=(locality),ST=(state),C=(country)" -keypass (password) -keystore client.keystore -storepass (password) # This command exports the client certificate. # The net result is a file called "client.cer" in your home directory. keytool -exportcert -rfc -alias (clientalias) -file client.cer -keypass (password) -keystore client.keystore -storepass (password) # This command imports the client certificate into the "tomcat.keystore" file. keytool -importcert -alias (clientalias) -file client.cer -keystore tomcat.keystore -storepass (password) -noprompt 

现在应该适当地设置证书。 下一步是在tomcat server.xml中配置连接器。 添加如下所示的连接器元素:

  

请注意,在上面的XML中:

  1. “port”属性可以是您想要的任何内容。
  2. “keystoreFile”和“truststoreFile”属性应该是完整路径。 默认情况下,Tomcat与server.xml不在同一目录中。
  3. “keystorePass”和“truststorePass”属性应与您在创建tomcat.keystore文件时使用的(密码)值相匹配。
  4. “clientAuth”属性必须设置为“true”。 这是触发相互身份validation的原因。

此外,在server.xml中,确保您没有定义AprLifecycleListner。 该侦听器的XML将如下所示:

  

应该删除/注释掉该元素。 AprLifecycleListener的配置方式与上述方法不同,并且不适用于这些说明。

重启tomcat。 服务器配置应该完整。

我使用Firefox测试了我的工作,因为很容易为它添加客户端证书。 打开Firefox并尝试在连接器中定义的端口上连接到tomcat服务的端点。

 Ex: https://mytomcatdomain.com:8443/test 

执行此操作时,您应该从Firefox获取有关不受信任连接的标准警报,因为我们为Tomcat服务器创建了自签名证书。 添加证书的例外,以便我们的客户端(Firefox)信任我们的服务器(Tomcat)。

添加例外后,您应该收到“安全连接失败”消息。 错误代码是“ssl_error_bad_cert_alert”。 这确认我们的Tomcat服务器正在请求来自客户端的身份validation。 请求失败,因为我们尚未将Firefox配置为发送我们的可信客户端证书。

要配置Firefox,我们需要做一些魔术:

 // Create a file called DumpPrivateKey.java. The contents should look like so: public class DumpPrivateKey { public static void main(String[] args) throws Exception { final String keystoreName = args[0]; final String keystorePassword = args[1]; final String alias = args[2]; java.security.KeyStore ks = java.security.KeyStore.getInstance("jks"); ks.load(new java.io.FileInputStream(keystoreName), keystorePassword.toCharArray()); System.out.println("-----BEGIN PRIVATE KEY-----"); System.out.println(new sun.misc.BASE64Encoder().encode(ks.getKey(alias, keystorePassword.toCharArray()).getEncoded())); System.out.println("-----END PRIVATE KEY-----"); } } 

使用以下命令编译java文件:

 javac DumpPrivateKey.java 

现在我们将使用这个小实用程序从我们上面创建的client.keystore文件中提取密钥。 将client.keystore和client.cer文件复制到与DumpPrivateKey类相同的目录中。 执行以下操作:

 # This extracts the client key from the client keystore java DumpPrivateKey client.keystore (password) clientkey > clientkey.pkcs8 # This creates a client.p12 file that can be used by Firefox openssl pkcs12 -export -in client.cer -inkey clientkey.pkcs8 -password pass:(password) -out client.p12 

请注意,在上面的代码中,(password)应该是您用来创建client.keystore的密码。

打开Firefox首选项。 单击“证书”选项卡。 单击“查看证书”按钮。 单击“您的证书”选项卡。

单击“导入”按钮并浏览到先前创建的“client.p12”文件。 系统将提示您输入客户端证书的密码。

假设已成功导入“client.p12”,您现在可以刷新Firefox页面,并且应该从Tomcat服务器端点获得成功响应。

@wbj,从JKS到PKCS#12的PrivateKeyEntry导出可以更容易:

 keytool -importkeystore -srckeystore client.keystore -destkeystore client.p12 -deststoretype PKCS12 -srcalias client -deststorepass  -destkeypass  

干杯。

我花了一些时间才能使用Openssl证书正确地工作,起草我的笔记,以便它可以帮助其他人访问此页面。

第1步:创建自己的根CA.

 ~/openssl$ mkdir -m 0700 /home/ubuntu/openssl/CA /home/ubuntu/openssl/CA/certs /home/ubuntu/openssl/CA/crl /home/ubuntu/openssl/CA/newcerts /home/ubuntu/openssl/CA/private ~/openssl$ touch /home/ubuntu/openssl/CA/indext.txt ~/openssl$ echo 1000 >> /home/ubuntu/openssl/CA/serial ~/openssl$ mv karun-tomcat-root-ca.key CA/private/ ~/openssl$ sudo vi /etc/openssl.cnf # Make changes here dir = /home/ubuntu/openssl/CA #optionally change policy definitions as well ~/openssl$ openssl genrsa -des3 -out karun-tomcat-root-ca.key 2048 #In below command make sure to use CN= ~/openssl$ openssl req -new -x509 -days 36520 -key karun-tomcat-root-ca.key -out karun-tomcat-root-ca.crt -config openssl.cnf ~$ sudo cp ~/openssl/CA/certs/karun-tomcat-root-ca.crt /usr/share/ca-certificates/ # make sure in the UI you enable/select the certificate created above ~$ sudo dpkg-reconfigure ca-certificates # Now reboot ubuntu machine just to make sure certificates are loaded successfully and tomcat picks it 

第2步:创建Tomcat服务器的密钥对

 ~$ openssl genrsa -out tomcat-server.key 2048 # Use common name = , department = Tomcat Server CSR ~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key tomcat-server.key -out tomcat-server.csr ~$ openssl x509 -req -sha256 -days 36520 -in tomcat-server.csr -signkey tomcat-server.key -CA ~/openssl/CA/certs/karun-tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-tomcat-root-ca.key -CAcreateserial -out tomcat-server.crt ~$ openssl pkcs12 -export -name karun-tomcat-server-cert -in tomcat-server.crt -out tomcat-server.p12 -inkey tomcat-server.key -CAfile ~/openssl/CA/certs/karun-tomcat-root-ca.crt -caname karun-root -chain ~$ keytool -importkeystore -destkeystore tomcat-server.jks -srckeystore tomcat-server.p12 -srcstoretype pkcs12 -alias karun-tomcat-server-cert ~$ keytool -import -alias karun-root -keystore tomcat-server.jks -trustcacerts -file ~/openssl/CA/certs/karun-tomcat-root-ca.crt # **(LATER)** Run this once client cert is generated ~$ keytool -importkeystore -alias karun-tomcat-client-cert -srckeystore ~/client-certs/tomcat-client.p12 -srcstoretype PKCS12 -destkeystore tomcat-server.jks -deststoretype JKS # **(LATER)** Run this once tomcat server started successfully ~$ openssl s_client -connect localhost:8443 -cert ~/client-certs/tomcat-client.crt -key ~/client-certs/tomcat-client.key -debug -showcerts 

第3步:创建客户端密钥对

 ~$ openssl genrsa -out tomcat-client.key 2048 # Use common name = , department = Tomcat Client CSR ~$ openssl req -new -sha256 -config ~/openssl/openssl.cnf -key tomcat-client.key -out tomcat-client.csr ~$ openssl x509 -req -sha256 -days 36520 -in tomcat-client.csr -signkey tomcat-client.key -CA ~/openssl/CA/certs/karun-tomcat-root-ca.crt -CAkey ~/openssl/CA/private/karun-tomcat-root-ca.key -CAcreateserial -out tomcat-client.crt ~$ openssl pkcs12 -export -name karun-tomcat-client-cert -in tomcat-client.crt -out tomcat-client.p12 -inkey tomcat-client.key -CAfile ~/openssl/CA/certs/karun-tomcat-root-ca.crt -caname karun-root -chain ~$ (optional step) keytool -importkeystore -destkeystore tomcat-client.jks -srckeystore tomcat-client.p12 -srcstoretype pkcs12 -alias karun-tomcat-client-cert ~$ (optional step) keytool -import -alias root -keystore tomcat-client.jks -trustcacerts -file ~/openssl/CA/certs/karun-tomcat-root-ca.crt 

第4步:Tomcat更改

 # Make this change in server.xml of tomcat server  

步骤5:重启Tomcat Server &&检查日志以确保启动时没有错误

步骤6:将客户端证书上载到浏览器

在您的浏览器中,例如:firefox,导航首选项 – >高级 – >证书 – >查看证书 – >您的证书

导入“tomcat-client.p12”

 https://:8443/ 

参考

http://pages.cs.wisc.edu/~zmiller/ca-howto/

http://www.area536.com/projects/be-your-own-certificate-authority-with-openssl/

我会尝试以下步骤

  1. 如您在8443上配置的那样假脱机容器。
  2. 使用-Djavax.net.debug = SSL运行客户端应用程序

该命令将清空PILES信息。 您需要检查的是服务器正在提供它将接受相互身份validation的CA列表。 如果列出的CA不包含您的证书,则客户端将不知道如何找到服务器的匹配项。

使用openssl命令’s_client’可以更轻松地做到这一点

 openssl s_client -connect localhost:8443 -showcerts 

这将格式化一些在调试它的价值中无法估量的信息。

如果服务器没有显示“可接受的”CA列表,那么在生成证书集时,您将不得不做一些魔术。

让我知道你发现了什么,我希望能引导你朝着正确的方向前进。

OP增加了额外的信息

好的,以下是您的一个问题:

 --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 263 bytes --- 

两件事立即跳出来

  1. 服务器没有对等证书
  2. 没有列出客户端CA名称

所以对于(1):

  1. 确保您的密钥库实际上使用keytool在其中具有别名“tomcat”。
  2. tomcat中的商店/密钥密码是傻瓜。 为了理智,将keystorePassword和keyPassword属性添加到具有相同值的连接器。 Tomcat 7的文档表明,如果未设置,keystorePass将默认为keyPass。 如果keyPass和keystorePass相同,则仅设置keyPass属性。

现在对于(2)我们真的需要(1)先工作 – 所以启动并运行,我们将看到我们在那一点。