与Tomcat 7的相互认证

 晒太阳的人2015 发布于 2022-12-07 12:25

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

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

//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: 

wbj.. 29

好的 - 在挖掘了更多之后,我终于得到了这个工作.非常感谢@Dave G和本教程:在Tomcat上配置双向SSL身份验证,其中大部分指令都是从这些身份验证中解释的.

通常,获得相互身份验证功能的步骤如下:

    为tomcat服务器创建证书.客户必须信任此证书.

    为tomcat服务器创建密钥库,并将服务器证书导入其中.

    为客户端创建证书.服务器必须信任此证书.

    客户端证书导入服务器密钥库

    使用正确的Connector XML更新tomcat server.xml文件.

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

    将客户端证书从服务器复制到客户端.

    与服务器通信时使用客户端证书(此过程因客户端应用程序的性质而异).

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

# 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中:

    "port"属性可以是您想要的任何内容.

    "keystoreFile"和"truststoreFile"属性应该是完整路径.默认情况下,Tomcat与server.xml不在同一目录中.

    "keystorePass"和"truststorePass"属性应与您在创建tomcat.keystore文件时使用的(密码)值相匹配.

    "clientAuth"属性必须设置为"true".这是触发相互身份验证的原因.

此外,在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服务器正在请求来自客户端的身份验证.请求失败,因为我们尚未将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服务器端点获得成功响应.

1 个回答
  • 好的 - 在挖掘了更多之后,我终于得到了这个工作.非常感谢@Dave G和本教程:在Tomcat上配置双向SSL身份验证,其中大部分指令都是从这些身份验证中解释的.

    通常,获得相互身份验证功能的步骤如下:

      为tomcat服务器创建证书.客户必须信任此证书.

      为tomcat服务器创建密钥库,并将服务器证书导入其中.

      为客户端创建证书.服务器必须信任此证书.

      客户端证书导入服务器密钥库

      使用正确的Connector XML更新tomcat server.xml文件.

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

      将客户端证书从服务器复制到客户端.

      与服务器通信时使用客户端证书(此过程因客户端应用程序的性质而异).

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

    # 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中配置连接器.添加如下所示的连接器元素:

    <Connector port="8443"
        maxThreads="150"
        scheme="https"
        secure="true"
        SSLEnabled="true"
        truststoreFile="/full/path/to/tomcat.keystore"
        truststorePass="(password)"
        keystoreFile="/full/path/to/tomcat.keystore"
        keystorePass="(password)"
        clientAuth="true"
        keyAlias="serverkey"
        sslProtocol="TLS"/>      
    

    请注意,在上面的XML中:

      "port"属性可以是您想要的任何内容.

      "keystoreFile"和"truststoreFile"属性应该是完整路径.默认情况下,Tomcat与server.xml不在同一目录中.

      "keystorePass"和"truststorePass"属性应与您在创建tomcat.keystore文件时使用的(密码)值相匹配.

      "clientAuth"属性必须设置为"true".这是触发相互身份验证的原因.

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

    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    

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

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

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

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

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

    添加例外后,您应该收到"安全连接失败"消息.错误代码是"ssl_error_bad_cert_alert".这确认我们的Tomcat服务器正在请求来自客户端的身份验证.请求失败,因为我们尚未将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服务器端点获得成功响应.

    2022-12-11 03:09 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有