我花了很长时间来研究这个问题,但我终于找到了一个真正有效的例子。它是基于Glassfish和Netbeans的,但我想如果你使用它,你可以让它在其他环境(例如Eclipse和Tomcat)中工作。
http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511
我发现的问题是,当你想使用自己的证书时,而不是那些预装在玻璃鱼上的证书。
注意:我不是安全专家。不要将其部署到生产环境!
为此,我使用了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 侦听器上启用安全性,勾选 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 服务属性”。勾选安全服务框,然后选择相互证书安全作为安全机制。单击配置...按钮,然后勾选“加密签名”框。现在取消选中使用开发默认值框,然后单击密钥库按钮。设置 server.jks 密钥库的位置并选择别名。对信任库配置执行相同的操作(尽管您不必在此处选择别名)。server
将 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.jks,并将别名设置为 。client1
server
希望您现在可以运行客户端,并且应该看到如下输出:EMAILADDRESS=bob@anonymous.org, CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US