Tomcat 服务器/客户端自签名 SSL 证书

Posted

技术标签:

【中文标题】Tomcat 服务器/客户端自签名 SSL 证书【英文标题】:Tomcat Server/Client Self-Signed SSL Certificate 【发布时间】:2010-11-13 21:40:33 【问题描述】:

我有一个运行自签名 SSL 证书的 Apache Tomcat 6.x 服务器。我希望客户端向服务器提供他们自己的证书,以便我可以根据用户数据库对它们进行身份验证。我根据我在网上找到的一个示例进行了所有工作,但是该示例附带了罐装证书和一个预构建的 JKS 数据存储。我想用自己的证书创建自己的数据存储,但没有运气。

如何为 Tomcat 创建数据存储? 如何为 Tomcat 创建自签名证书?

如何为客户端创建自签名证书? 如何强制 Tomcat 信任客户端的签名?

我已经用 java keytool 玩了好几个小时了。

【问题讨论】:

【参考方案1】:

终于找到了解决我的问题的方法,所以如果其他人卡住了,我会在这里发布结果。

感谢Michael's Software Thoughts & Ramblings 的 Michael Martin,我发现:

keytool 默认使用 DSA 生成算法时 自签名证书。早期版本的 Firefox 接受了这些密钥 问题。使用 Firefox 3 beta 5,使用 DSA 不起作用,但使用 RSA 可以。 生成时传递“-keyalg RSA” 自签名证书创建一个 完全认证 Firefox 3 beta 5 接受。

我只是设置了那个标志,清除了 FireFox 中的所有缓存,它就像一个魅力!我将它用作我的项目的测试设置,我需要与其他人分享它,所以我编写了一个小批处理脚本来创建两个 SSL 证书。一个可以放入 Tomcat 设置中,另一个是可以导入 FireFox/IE 的 .p12 文件。谢谢!

用法:第一个命令行参数是客户端的用户名。所有密码都是“密码”(不带引号)。更改任何硬编码位以满足您的需要。

@echo off
if "%1" == "" goto usage

keytool -genkeypair -alias servercert -keyalg RSA -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass password -keystore server.jks -storepass password
keytool -genkeypair -alias %1 -keystore %1.p12 -storetype pkcs12 -keyalg RSA -dname "CN=%1,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass password -storepass password
keytool -exportcert -alias %1 -file %1.cer -keystore %1.p12 -storetype pkcs12 -storepass password
keytool -importcert -keystore server.jks -alias %1 -file %1.cer -v -trustcacerts -noprompt -storepass password
keytool -list -v -keystore server.jks -storepass password
del %1.cer
goto end

:usage
echo Need user id as first argument: generate_keystore [username]
goto end

:end
pause

结果是两个文件。一个名为 server.jks 的文件放入 Tomcat,另一个名为 username.p12 的文件导入浏览器。 server.jks 文件将客户端证书添加为可信证书。

我希望其他人觉得这很有用。

这里是需要添加到 Tomcat conf/sever.xml 文件中的 XML(仅在 Tomcat 6.x 上测试过)

<Connector
   clientAuth="true" port="8443" minSpareThreads="5" maxSpareThreads="75"
   enableLookups="true" disableUploadTimeout="true"
   acceptCount="100" maxThreads="200"
   scheme="https" secure="true" SSLEnabled="true"
   keystoreFile="$catalina.home/conf/server.jks"
   keystoreType="JKS" keystorePass="password"
   truststoreFile="$catalina.home/conf/server.jks"
   truststoreType="JKS" truststorePass="password"
   SSLVerifyClient="require" SSLEngine="on" SSLVerifyDepth="2" sslProtocol="TLS"
/>

对于 Tomcat 7:

<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
           port="8443" SSLEnabled="true"
           maxThreads="200" scheme="https" secure="true"
           keystoreFile="$catalina.base/conf/server.jks" keystorePass="password"
           clientAuth="false" sslProtocol="TLS" />    

【讨论】:

非常感谢!我整天都在搞各种“教程”,这是第一个真正适用于 clientAuth="true" 的教程。 这是一个漂亮的答案。我用 bat 文件节省了很多时间。最棒的是它运行良好。 请注意,此答案将服务器和客户端证书都放在 server.jks 中,但服务器使用的证书未定义(当前实现恰好将第一个添加到密钥库)。您应该添加 keyAlias="servercert" 以使其更加健壮。【参考方案2】:

要启用客户端身份验证,您需要为 Tomcat 指定一个“信任库”:一个包含来自您信任的根证书颁发机构的证书的密钥库,每个都标记为“trustEntry”。

这是由 Connector 元素的属性指定的:truststoreFiletruststorePass(默认为 keystorePass 的值)和 truststoreType(默认为“JKS”)。

如果客户端使用的是自签名证书,那么它的“根”CA 就是证书本身;因此,您需要将客户端的自签名证书导入到 Tomcat 的信任库中。

如果您有很多客户,这很快就会变得很麻烦。在这种情况下,您可能需要考虑为您的客户签署证书。 Java keytool 命令不能做到这一点,但所有必要的命令行实用程序都可以在 OpenSSL 中使用。或者,您可以大规模研究EJBCA 之类的内容。

更好的是,让您的客户使用现有的免费 CA,例如 startcom.org。这并不总是适用于服务器证书,因为并非所有浏览器都包含 StartCom 的证书,但这种情况正好相反,并且 StartCom 根证书可以很容易地导入到 Tomcat 信任库中。

【讨论】:

【参考方案3】:

创建证书:

keytool -genkey -alias tomcat -keyalg RSA -keystore /home/bob/mykeystore

输入您需要的自签名证书的所有数据,然后编辑 Tomcat 的 server.xml 并在 SSL 连接器上指定密钥库属性,例如:

<Connector port="8443" maxHttpHeaderSize="8192"
        maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
        enableLookups="false" disableUploadTimeout="true"
        acceptCount="100" scheme="https" secure="true"
        keystoreFile="/home/bob/mykeystore"
        clientAuth="false" sslProtocol="TLS" />

或遵循 Tomcat 文档...

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

【讨论】:

我早些时候看到了,它得到了我的一半答案,但你错过了更棘手的部分。如何使用自签名客户端证书?在您提供的示例中,它显示“clientAuth='false'”。当设置为“真”时,我需要它工作。”“如果您希望 Tomcat 要求所有 SSL 客户端提供客户端证书以使用此套接字,请将此值设置为真。”这就是我想要的。但我不能让服务器接受客户端的自签名证书。【参考方案4】:

以前的答案对我有用,但没有shell工具版本。所以我写了一个。

key_gen.sh:

#! /bin/bash
# a key generator for https,

basename=server
key_algorithm=RSA
password_key=123456
password_store=123456
country=US

# clean - pre
rm "$basename.jks"

# generate server side
keytool -genkeypair -alias "$basenamecert" -keyalg $key_algorithm -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=$country" -keypass $password_key -keystore "$basename.jks" -storepass $password_store

对于tomcat8,可以将以下配置添加到server.xml

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
        maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
        clientAuth="false" sslProtocol="TLS"
        acceptCount="75" keystoreFile="$catalina.home/conf/server.jks" keystorePass="123456"
    />

【讨论】:

以上是关于Tomcat 服务器/客户端自签名 SSL 证书的主要内容,如果未能解决你的问题,请参考以下文章

如何创建用于 Tomcat 的自签名 SSL 证书?

Android使用SSL自签名证书

Android使用SSL自签名证书

Android使用SSL自签名证书

SSL 认证问题 - 使用 Tomcat 的 Spring 和本地自签名证书

Java:使用自签名证书的 SSL 客户端身份验证