Java 与web服务的相互身份验证

Java 与web服务的相互身份验证,java,web-services,authentication,pki,mutual-authentication,Java,Web Services,Authentication,Pki,Mutual Authentication,目前,只要客户端使用web浏览器访问网站,我就成功地实现了相互身份验证安全性,因为浏览器为您处理所有证书交换。现在,我需要创建一个安全接口,用户可以使用服务器所需的相互身份验证通过HTTPS访问web服务 首先,有没有任何人知道的资源可以帮助我解决这个问题?我找了很长时间,什么也没找到。有没有其他人能给我的建议 其次,我认为我最大的障碍是我不了解如何处理证书。我如何协商接受服务器的密钥并向服务器提供我自己的密钥?这是Java语言。中给出了一个简单的配方 但我认为真正的答案可能取决于您使用什么Ja

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

首先,有没有任何人知道的资源可以帮助我解决这个问题?我找了很长时间,什么也没找到。有没有其他人能给我的建议


其次,我认为我最大的障碍是我不了解如何处理证书。我如何协商接受服务器的密钥并向服务器提供我自己的密钥?这是Java语言。

中给出了一个简单的配方


但我认为真正的答案可能取决于您使用什么JavaAPI来实现客户端HTTP交互。例如,您可能会使用JAX-RPC进行操作。

如果web服务库使用标准的
java.net.URL
类作为HTTP客户端,您可以设置一些,双向身份验证将由内置的HTTPS支持来处理

这些措施包括:

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

这些设置将成为进程中所有SSL连接的默认设置。如果您想要更好的控制,您必须设置自己的
SSLContext
。您的webservice运行时是否可能实现这一点取决于您选择的运行时。

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

  • 服务器密钥库
  • 客户信任库
  • 服务器密钥库包含服务器的(可能是自签名的)证书和私钥。服务器使用此存储对消息进行签名并将凭据返回给客户端

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

    通过这种方式,您可以实现单向SSL(传统用例)

    要实现双向SSL,您需要使此设置“对称”,因此我们需要添加:

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

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

    一些资源可帮助您生成所有这些内容并实施最终解决方案:


    我花了很长时间在这方面,但我最终找到了一个实际可行的例子。它是基于Glassfish和Netbeans的,但我想如果您使用它,您可以在其他环境(例如Eclipse和Tomcat)中使用它

    但我发现的问题是,当您想要使用自己的证书,而不是glassfish预装的证书时

    注意:我不是安全专家。不要将其部署到生产环境中

    为此,我使用了NetBeans 6.9、JDK 1.6、GlassFish 3.0.1和OpenSSL v1.0(我使用的是非官方的Win32二进制文件)

    在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();
      }
    
    }
    
    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());
    }
    
    右键单击Web服务并选择编辑Web服务属性。勾选安全服务框,并选择相互证书安全性作为安全机制。单击配置。。。按钮并勾选加密签名框。现在取消选中UseDevelopmentDefaults框,然后单击Keystore按钮。设置server.jks密钥库的位置并选择
    服务器
    别名。对信任库配置执行相同的操作(尽管您不必在此处选择别名)

    将client1.p12客户端证书导入浏览器。将Web服务部署到Glassfish。在浏览器中打开web服务,并通过HTTPS浏览到已部署的WSDL。下载WSDL和任何其他模式。将任何引用的架构重命名为本地副本,以便在使用WSDL2Java NetBeans时不会使用任何远程资源。(这一段是因为您已将WSDL限制为具有已批准证书的客户端,但NetBeans无法远程获取它,因为它无权访问所讨论的证书)

    创建一个新的Java项目。创建一个新的Web服务客户端。出现提示时,将NetBeans指向保存的WSDL文件。导入METRO2.0库文件(
    C:\ProgramFiles\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar
    )。我的代码如下所示:

    @WebService()
    public class ListProducts {
    
      @Resource WebServiceContext context;
    
      @WebMethod(operationName = "listProducts")
      public String listProducts() {
        return context.getUserPrincipal().toString();
      }
    
    }
    
    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\approved目录中。 右键单击Web服务引用并选择