Java 如何使用keystore.jks对SOAP消息进行签名和加密

Java 如何使用keystore.jks对SOAP消息进行签名和加密,java,web-services,encryption,soap,Java,Web Services,Encryption,Soap,我是web服务安全新手,正在尝试学习如何对soap消息请求进行签名和加密。 我读过很多与这个话题相关的帖子,但似乎有太多不同的方法,我很困惑该怎么走 我有一个功能正常的web服务(SOAP)。我还有一个keystore.jks文件,其中包含2个条目 第一个条目类型是trustedCertEntry。(X.509/RSA公钥) 第二种条目类型是privateKeyEntry 我的理解是keystore包含凭据,而truststore包含受信任网站(服务器)的列表。 所以“…\jdk1.6.0_19

我是web服务安全新手,正在尝试学习如何对soap消息请求进行签名和加密。 我读过很多与这个话题相关的帖子,但似乎有太多不同的方法,我很困惑该怎么走

我有一个功能正常的web服务(SOAP)。我还有一个keystore.jks文件,其中包含2个条目

第一个条目类型是trustedCertEntry。(X.509/RSA公钥)

第二种条目类型是privateKeyEntry

我的理解是keystore包含凭据,而truststore包含受信任网站(服务器)的列表。 所以“…\jdk1.6.0_19\jre\lib\security\cacerts”是我的信任库,keystore.jks是我的密钥库

我假设我需要使用密钥库凭据对soap消息进行签名和加密。 但我仍然不清楚如何实现这一目标

我可以拿到X.509证书

KeyStore ks = KeyStore.getInstance(KEYSTORE_INSTANCE);
ks.load(new FileInputStream(KEYSTORE_FILE), KEYSTORE_PWD.toCharArray());
ks.getCertificate(KEYSTORE_ALIAS);
我还可以获得私钥:

KeyStore.Entry entry = ks_pk.getEntry(KEYSTORE_ALIAS_PK, new KeyStore.PasswordProtection(pass));
因此,我可以从密钥库获取信息,但我不确定如何使用它来签名和加密我的SOAP请求消息

我是否需要将签名添加为另一个SOAPheader元素? 如何加密邮件


任何指针、代码示例和提示都将不胜感激。

我正在使用Apache CXF for client和Rampart对SOAP消息进行签名和加密。此Rampart包实现WSS标准

在客户端项目中,在pom.xml中添加以下依赖项[检查可用的最新版本]

<dependency>
    <groupId>org.apache.rampart</groupId>
    <artifactId>rampart-policy</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>org.apache.rampart</groupId>
    <artifactId>rampart-core</artifactId>
    <version>1.4</version>
</dependency>
然后修改客户机类以提供Rampart执行签名所需的信息

添加以下导入:

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.ws.security.WSPasswordCallback;
//实现回调处理程序以检索密码

SService ss = new SService(wsdlURL, SERVICE_NAME);
Service port = service.getPort1();
BindingProvider bp = (BindingProvider) port;
Map<String, Object> context = bp.getRequestContext();
//c1 is The alias of the entry in the keystore
context.put(SecurityConstants.SIGNATURE_USERNAME, "c1");
context.put(SecurityConstants.CALLBACK_HANDLER, new CallbackHandler() {
    @Override
    public void handle(Callback[] callbacks) throws IOException,
    UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
                WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];
                String id = pwcb.getIdentifier();
                if (id.equals("c1")) {
                pwcb.setPassword("c1-pass");
            }
        }
    }
    });
context .put(SecurityConstants.SIGNATURE_PROPERTIES, "crypto.properties");
SService ss=新的SService(wsdlURL,服务名称);
服务端口=Service.getPort1();
BindingProvider bp=(BindingProvider)端口;
Map context=bp.getRequestContext();
//c1是密钥库中条目的别名
context.put(SecurityConstants.SIGNATURE_用户名,“c1”);
put(SecurityConstants.CALLBACK\u处理程序,new CallbackHandler(){
@凌驾
公共无效句柄(回调[]回调)引发IOException,
不支持CallbackException{
for(int i=0;i
到目前为止,您在实施过程中使用了哪些工具/框架?如果客户端应该发送加密消息,则私钥将保留在服务器端(web服务)。封装在X509证书中的公钥将位于客户端。私钥是在Web服务上配置的密钥库的一部分,而公共证书是在客户端配置的信任库的一部分。@ringbearer-感谢您的见解。我正在使用EclipseLuna和Keytool插件。我在本地主机(在Eclipse中)的tomcat-6.0.44上运行了一个虚拟服务?CXF?春天Java EE?这个细节会很有帮助,因为解决方案依赖于这些。@ringbearer-Oops,对不起。。。javaee。
SService ss = new SService(wsdlURL, SERVICE_NAME);
Service port = service.getPort1();
BindingProvider bp = (BindingProvider) port;
Map<String, Object> context = bp.getRequestContext();
//c1 is The alias of the entry in the keystore
context.put(SecurityConstants.SIGNATURE_USERNAME, "c1");
context.put(SecurityConstants.CALLBACK_HANDLER, new CallbackHandler() {
    @Override
    public void handle(Callback[] callbacks) throws IOException,
    UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
                WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];
                String id = pwcb.getIdentifier();
                if (id.equals("c1")) {
                pwcb.setPassword("c1-pass");
            }
        }
    }
    });
context .put(SecurityConstants.SIGNATURE_PROPERTIES, "crypto.properties");