用于GAE(java)上web服务的双向SSL

用于GAE(java)上web服务的双向SSL,java,web-services,google-app-engine,ssl,pki,Java,Web Services,Google App Engine,Ssl,Pki,我们需要在googleappengine上实现双向SSL,在这里,我们使用JAX-WS向服务器发送web服务请求,请求双向SSL身份验证 如何为传出的web服务请求设置双向SSL 我们知道javax.net.ssl*在应用程序引擎环境中是被禁止的 下面是我们的代码示例: @WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl") @SOAPBinding(parameterStyle

我们需要在googleappengine上实现双向SSL,在这里,我们使用JAX-WS向服务器发送web服务请求,请求双向SSL身份验证

如何为传出的web服务请求设置双向SSL

我们知道
javax.net.ssl*
在应用程序引擎环境中是被禁止的

下面是我们的代码示例:

@WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {

    @WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
    public void ping();
}

@WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
  public ListenerSoap getListenerSoap() {
   return super.getPort(new QName("http://example.com/Listener.Wsdl", 
                       "ListenerSoap"), ListenerSoap.class);
  }
}
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
以及上述正在使用的代码示例:

@WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {

    @WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
    public void ping();
}

@WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
  public ListenerSoap getListenerSoap() {
   return super.getPort(new QName("http://example.com/Listener.Wsdl", 
                       "ListenerSoap"), ListenerSoap.class);
  }
}
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
我认为我们可以将密钥存储库或数据存储中所需的任何证书存储为二进制对象(尽管如何上传它们对我来说仍然是一个很模糊的问题)

我们如何设置此web服务使用双向SSL进行身份验证所需的必要值

谢谢你的帮助

更新:

@WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {

    @WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
    public void ping();
}

@WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
  public ListenerSoap getListenerSoap() {
   return super.getPort(new QName("http://example.com/Listener.Wsdl", 
                       "ListenerSoap"), ListenerSoap.class);
  }
}
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
通过研究,我发现这是如何在传统服务器(具有文件系统访问权限的服务器)上实现的:

但是,在这种方法中,
client\u cert.p12
应该位于文件系统上

此外,
SSLSocketFactory
SSLContext
KeyManager
KeyManagerFactory
都不允许在GAE上使用

更新:

@WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {

    @WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
    public void ping();
}

@WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
  public ListenerSoap getListenerSoap() {
   return super.getPort(new QName("http://example.com/Listener.Wsdl", 
                       "ListenerSoap"), ListenerSoap.class);
  }
}
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
从GAE SDK版本1.7.7开始。现在应该可以做到这一点:

Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections.

据我所知,双向SSL与Java EE代码没有链接:双向SSL是一种传输层安全性:当您的客户端应用程序尝试与服务创建安全HTTP连接(HTTPS)时,服务器将请求证书并批准或不批准此证书。如果客户端证书获得批准,则将在各方上建立安全连接,并允许他们通过此隧道交换一些消息。但是这个过程是在传输层完成的。您的代码(在应用层)将永远不会被告知此过程。 为了建立双向SSL,在应用程序服务器上完成SSL端口的设置

ListenerSoap soap = new Listener().getListenerSoap();
希望情况有所改善


谢谢

我知道您可能不想听这个,但是使用SSL对于双向通信来说是昂贵且有问题的。根据您对服务器/客户端的控制程度,我更喜欢简单的双向管道(如web套接字)和可以简单实现AES的数据包协议。这实际上取决于您试图解决的问题。

这听起来像是对SSL上的简单连接的混淆(
https://...
)以及所谓的“相互认证”或“公钥基础设施(PKI)”。实际上,你可以同时做这两件事,或者一件独立于另一件。对于后者(我认为原始问题所指的),当您向服务器发出请求时,服务器将响应您的请求,要求您提供一个证书,您必须出示该证书才能进行身份验证


要回答上面的特定问题(从二进制数据加载密钥库),我认为这是不可能的,因为是Java运行时获取密钥库。您唯一能做的就是从数据存储中加载位并将其临时写入磁盘。当应用程序存在时,可以选择删除它。这是我以前做过的,效果相当不错。如果您这样做,我建议您使用一个可能是可写的位置(例如
System.getProperty(“java.io.tmpdir”)),然后在将文件写入磁盘后,设置JVM属性(例如,
System.getProperties().put(“javax.net.ssl.keyStore”,“…”);

为此,您需要应用程序引擎的套接字API。此API处于trusted tester模式,因此并非每个人都可以使用


您可以请求访问gere:

根据我对SSL授权的有限了解,您可能缺少一些至关重要的信息;证书。双向SSL要求客户端和服务器证书位于您的密钥库中,可以是自签名证书(pkcs12或pem文件,您可以通过shell通过几个命令轻松生成),也可以是由授权公司(如Thawte或Verisign)颁发的专有证书。 虽然我不确定这是否是你所面临的问题,但检查一下是件好事。
(另外,我是一个新手,所以请不要否决我的答案,只是尝试建议可能的选项。)

据我所知,双向SSL(从GAE托管的应用程序到外部世界)不受支持。几个月前,我尝试了一个示例应用程序,但很沮丧地发现GAE甚至不支持这个基本功能。。文件也不清楚。当您联系web服务时,将无法显示客户端证书。。没有存储它的地方,无法访问密钥库。

在URLFetch服务中有一个支持客户端证书的开放功能请求:这绝对不是真的。完全可以通过应用程序代码建立双向SSL连接,例如设置
systemProps.put(“javax.net.SSL.keyStore”,keyStorePath)例如。问题是GAE将
java.net.ssl*
软件包列入黑名单,因此在撰写本文时不可能在GAE上这样做。我应该承认我错了。下面是一个关于如何在java代码中实现双向SSL的示例代码:这在GAE上仍然不起作用,因为所有类都在
javax.net.SSL.*
包下被列入黑名单,包括
SSLSocket
SSLSocketFactory
是的,这甚至包括在帖子中。。。问题是如何让双向SSL在GAE上工作——这似乎是不可行的任务。我认为OP谈论的是双向授权(实际上是身份验证)。双向通信是安全的;公钥/私钥用于交换双方用于加密的对称密钥。这个问题是关于在客户机和服务器上使用证书来相互验证。是的,我们需要这个证书来验证和满足合作伙伴的软件需求。如果我们选择