与Web服务的相互身份验证

bkr*_*zer 22 java authentication web-services pki mutual-authentication

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

首先,有没有人知道的资源可以帮助我吗?我已经找了很长时间没找到.任何其他人可以给我如何解决这个问题的提示?

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

Cat*_*hwa 14

我花了很长时间在这上面,但我终于找到了一个实际可行的例子.它是基于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"
Run Code Online (Sandbox Code Playgroud)

在GlassFish管理控制台中,在http-listener上启用Security,勾选SSL3,TLS和Client Authentication框,将Certificate NickName设置为server,将密钥存储设置为config\keystore.jks,将Trust Store设置为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();
  }

}
Run Code Online (Sandbox Code Playgroud)

右键单击Web Service,然后选择"编辑Web服务属性".选中Secure Service框并选择Mutual Certificates Security作为安全机制.单击Configure ...按钮并勾选Encrypt Signature框.现在取消勾选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());
}
Run Code Online (Sandbox Code Playgroud)

将webservices-api.jar复制到Java\jdk1.6\jre\lib\endorsed目录中.右键单击Web Service引用,然后选择"编辑Web服务属性".将密钥库位置设置为client1.jks并将别名设置为client1.将truststore位置设置为client1.jks并将别名设置为server.

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


Pas*_*ent 13

对于在浏览器之外使用SSL(也称为双向SSL)进行相互身份验证,您需要......实际上,让我们先看看您对单向SSL的需求:

  1. 服务器密钥库
  2. 客户端信任库

服务器密钥库包含服务器(可能是自签名)证书和私钥.服务器使用此存储来签署消息并将凭据返回给客户端.

客户端信任库包含服务器的(自签名)证书(从服务器密钥库提取到独立证书中,不包含服务器私钥).如果证书未由您在JRE捆绑的信任库中已拥有证书的可信CA签名,则必须执行此操作.此步骤允许创建信任链.

有了这个,您可以实现单向SSL(传统的用例).

要实现双向SSL,您需要将此设置设置为"对称",因此我们需要添加:

  1. 客户端密钥库
  2. 服务器信任库

客户端密钥库包含客户端(可能是自签名)证书和私钥.客户端使用此存储的目的与服务器密钥库相同,即在TLS相互身份验证握手期间将客户端凭据发送到服务器.

服务器信任库包含客户端(自签名)独立证书(从客户端密钥库提取到独立证书,而不包含客户端私钥).出于与前面提到的完全相同的原因,这是必需的.

一些资源可以帮助您生成所有这些东西并实现最终解决方案:

  • 虽然您已经很好地解释了相互认证概念,但链接根本不是很有帮助.自2006年以来,Java Web服务安全性发生了翻天覆地的变化!:) (3认同)

eri*_*son 6

如果Web服务库将标准java.net.URL类用作HTTP客户端,则可以设置一些系统属性,并且内置HTTPS支持将处理双向身份验证.

必要的属性有:

  • javax.net.ssl.trustStore:包含根CA证书
  • javax.net.ssl.keyStore:包含客户端证书和私钥
  • javax.net.ssl.keyStorePassword:保护客户端私钥的密码

这些设置成为进程的所有SSL连接的默认设置.如果你想要更好的控制,你必须自己设置SSLContext.您的Web服务运行时是否可行取决于您选择的运行时.


Ste*_*n C 1

这篇博客文章中给出了一个简单的食谱。

但我认为真正的答案可能取决于您使用什么 Java API 来实现客户端 HTTP 交互。例如,看起来您会使用 JAX-RPC 做一些不同的事情。