java - 与 Web 服务的相互身份验证

标签 java web-services authentication pki mutual-authentication

目前,只要客户端使用网络浏览器访问网站,我就已经成功实现了相互身份验证安全性,因为浏览器会为您处理所有证书交换。现在我需要创建一个安全接口(interface),用户可以使用该接口(interface)通过 HTTPS 访问 Web 服务,使用服务器所需的相互身份验证。

首先,是否有任何人知道的资源可以帮助我解决这个问题?我已经找了很长时间了,什么也没找到。任何人都可以给我关于如何解决这个问题的任何其他提示?

其次,我认为我最大的障碍是我对如何处理证书缺乏了解。如何协商接受服务器的 key 并将我自己的 key 提供给服务器?这是在 Java 中。

最佳答案

我在这方面花了很长时间,但我终于找到了一个真正有效的例子。它是基于 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 和客户端身份验证框,将证书昵称设置为服务器,将 keystore 设置为 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 keystore 的位置并选择 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 服务属性。将 keystore 位置设置为 client1.jks 并将别名设置为 client1。将信任库位置设置为 client1.jks 并将别名设置为 server

希望您现在可以运行您的客户端,您应该会看到如下输出: EMAILADDRESS=bob@anonymous.org, CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

关于java - 与 Web 服务的相互身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2240931/

相关文章:

PHP Web 服务队列

web-services - 具有动态 uri 的 spring 集成出站 web 服务网关并信任所有证书

c# - 将远程 SQL Server 数据库与本地 SQL Server Compact 数据库同步的最佳方法?

authentication - 护照和智威汤逊的区别?

java - Eclipse Web 服务资源管理器如何工作?

java - 如何使用 Eclipse 中包含的外部库创建 jar?

java - 限制映射以获得基于 JPA 的排序的特定一对一关系

java - 属性值历史模式

amazon-web-services - AWS Lambda 中 id_token 与 access_token 使用的最佳实践

php - 在 laravel 中重定向到外部 url 时如何保留 session 数据