我在这方面花了很长时间,但我终于找到了一个真正有效的例子。它是基于 Glassfish 和 Netbeans 的,但我想如果你使用它,你可以让它在其他环境(例如 Eclipse 和 Tomcat)中工作。
http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511
我发现的问题是当您想使用自己的证书时,而不是使用 glassfish 预装的证书。
注意:我不是安全专家。不要将其部署到生产环境!
为此,我使用的是 NetBeans 6.9、JDK 1.6、GlassFish 3.0.1 和 OpenSSL v1.0(我使用的是非官方的 Win32 二进制文件)
# Create the CA
mkdir ca server client
cd ca
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem
echo 02 > serial.txt
cd ..
# Creating the Server Keystore
openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer
# Create the Client Keystore
openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer
# Import public keys and certificates into each others keystores
keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks"
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts"
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup"
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks"
在 GlassFish 管理控制台中,在您的 http-listener 上启用安全性,勾选 SSL3、TLS 和客户端身份验证框,将证书昵称设置为服务器,将密钥库设置为 config\keystore.jks,将信任库设置为 config\ keystore.jks,PKIX 的信任算法,并将最大证书长度保留为 5。
在 NetBeans 中,创建一个新的 Web 应用程序项目。在其中创建一个新的 Web 服务。
我的 Web 服务代码如下所示:
@WebService()
public class ListProducts {
@Resource WebServiceContext context;
@WebMethod(operationName = "listProducts")
public String listProducts() {
return context.getUserPrincipal().toString();
}
}
右键单击 Web 服务并选择编辑 Web 服务属性。勾选 Secure Service 框并选择 Mutual Certificates Security 作为安全机制。单击配置...按钮并勾选加密签名框。现在取消选中 Use Development Defaults 框,然后单击 Keystore 按钮。设置 server.jks 密钥库的位置并选择 server 别名。对 Truststore 配置执行相同的操作(尽管您不必在此处选择别名)。
将 client1.p12 客户端证书导入浏览器。将您的 Web 服务部署到 Glassfish。在浏览器中打开您的 Web 服务并通过 HTTPS 浏览到已部署的 WSDL。下载 WSDL 和任何其他模式。将任何引用的模式重命名为本地副本,以便在您使用 WSDL2Java 时,NetBeans 不会使用任何远程资源。 (本段是因为您已将 WSDL 限制为具有批准证书的客户端,但 NetBeans 无法远程获取它,因为它无权访问相关证书)。
创建一个新的 Java 项目。创建一个新的 Web 服务客户端。出现提示时,将 NetBeans 指向您保存的 WSDL 文件。导入 METRO2.0 库文件 (C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar)。我的代码如下所示:
public static void main(String[] args) {
System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit");
System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit");
System.out.println(new ListProductsService().getListProductsPort().listProducts());
}
将 webservices-api.jar 复制到您的 Java\jdk1.6\jre\lib\endorsed 目录中。
右键单击 Web 服务引用并选择编辑 Web 服务属性。将密钥库位置设置为 client1.jks 并将别名设置为 client1。将信任库位置设置为 client1.jks,并将别名设置为 server。
希望您现在可以运行您的客户端,您应该会看到如下输出:
EMAILADDRESS=bob@anonymous.org, CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US