java - 如何手动加密 SOAP 消息?

标签 java web-services security jboss ws-security

我使用 JBoss 4.2.3.GA。在之前的任务中,我使用了 JBoss 支持的基本加密机制 (WS-Security)。 IE。我使用 keystore 、信任库文件来加密和签名消息。通常(以标准方式)在 jboss-wsse-* 文件中定义了必须在加密过程中使用的 key 别名。我在 Action book 中使用了 JBoss 的 ws 安全配置。

没关系。加密工作正常。

但在我当前的任务中,我需要手动和动态地为键指定别名。 任务说明:

  • 我有几个个人资料。在每个配置文件中都可以指定必须用于加密消息的公钥的别名。

  • 我的 keystore 包含服务器的私钥/公钥和将向服务器发送消息的客户端的公钥

  • 我需要从配置文件中获取别名并使用此别名指定的公钥加密消息(在客户端)。

  • 所以我需要以某种方式从 keystore 加载数据(它必须驻留在文件系统文件夹中,即在 ear 文件之外),从中获取适当的公钥然后进行加密。
  • 之后,我需要将消息发送到具有用于解密的私钥的远程 Web 服务(服务器端)。
  • 在这里,我看到了服务器端逻辑的几种变体:Web 服务使用标准 JBoss 机制进行解密,或者我可以手动加载 keystore 数据并手动进行解密。

所以问题是:

  1. 有没有办法为 JBoss 指定从中加载 keystore 的文件系统目录?
  2. 我可以为标准 JBoss WSS 机制指定别名以允许 jboss 在加密过程中使用此信息吗?
  3. 如果我必须进行手动加密/解密,那么我如何将多个 Java 对象包装到 WS 消息中然后使用必要的别名对其进行加密如何发送它手动向远程网络服务发送消息?

我只是不知道如何开始,使用什么框架,甚至是否有必要为此使用外部(非 JBoss)框架...

最佳答案

如果可能,您可以使用 Axis2 和 Rampart。我已经在类似情况下成功地使用了它们。

Rampart 是一个用于处理安全性的 axis2 模块,它公开了一个 API,允许您定义 key 存储位置和要使用的别名,从而允许您动态定义它。

Axis2

Rampart

示例代码:

private static final String CONFIGURATION_CTX = "src/ctx";  
private static final String KEYSTORE_TYPE = "org.apache.ws.security.crypto.merlin.keystore.type";
private static final String KEYSTORE_FILE = "org.apache.ws.security.crypto.merlin.file";
private static final String KEYSTORE_PWD = "org.apache.ws.security.crypto.merlin.keystore.password";
private static final String PROVIDER = "org.apache.ws.security.components.crypto.Merlin";

private static void engageRampartModules(Stub stub)
throws AxisFault, FileNotFoundException, XMLStreamException {
    ServiceClient serviceClient = stub._getServiceClient();

    engageAddressingModule(stub);   
    serviceClient.engageModule("rampart");
    serviceClient.engageModule("rahas");

    RampartConfig rampartConfig = prepareRampartConfig();  

    attachPolicy(stub,rampartConfig);
}

/**
 * Sets all the required security properties.
 * @return rampartConfig - an object containing rampart configurations
 */
private static RampartConfig prepareRampartConfig() {
    String certAlias = "alias";             //The alias of the public key in the jks file
    String keyStoreFile = "ctx/client.ks";
    String keystorePassword = "pwd";
    String userName = "youusename";


    RampartConfig rampartConfig = new RampartConfig();
    //Define properties for signing and encription
    Properties merlinProp = new Properties();  
    merlinProp.put(KEYSTORE_TYPE, "JKS");  
    merlinProp.put(KEYSTORE_FILE,keyStoreFile);  
    merlinProp.put(KEYSTORE_PWD, keystorePassword); 

    CryptoConfig cryptoConfig = new CryptoConfig();  
    cryptoConfig.setProvider(PROVIDER);  
    cryptoConfig.setProp(merlinProp);  

    //Rampart configurations
    rampartConfig.setUser(userName);
    rampartConfig.setUserCertAlias(certAlias);  
    rampartConfig.setEncryptionUser(certAlias);  
    rampartConfig.setPwCbClass("com.callback.tests.PasswordCallbackHandler"); //Password Callbak class

    rampartConfig.setSigCryptoConfig(cryptoConfig);  
    rampartConfig.setEncrCryptoConfig(cryptoConfig);
    return rampartConfig;
}

/**
 * attach the security policy to the stub.
 * @param stub
 * @param rampartConfig
 * @throws XMLStreamException
 * @throws FileNotFoundException
 */
private static void attachPolicy(Stub stub, RampartConfig rampartConfig) throws XMLStreamException, FileNotFoundException {
    Policy policy = new Policy();
    policy.addAssertion(rampartConfig);
    stub._getServiceClient().getAxisService().getPolicySubject().attachPolicy(policy);
}

密码回调处理程序:

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class PasswordCallbackHandler implements 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.getIdentifer();
        switch (pwcb.getUsage()) {
            case WSPasswordCallback.USERNAME_TOKEN: {
                if (id.equals("pwd")) {
                    pwcb.setPassword("pwd");
                }
            }
        }
    }
}

关于java - 如何手动加密 SOAP 消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6368714/

相关文章:

java - 使用权限运行小程序的 Eclipse 应用程序

ruby-on-rails - 如何创建一个网络服务

java - 如何从 Java 应用程序获取远程 HTTPS 服务器支持的密码列表?

python - 在服务器上安全地执行不受信任的Python代码

java - iText 选择保存 PDF 的路径

java - 使用 Spring Cloud 连接器访问 CloudFoundry 用户提供的服务

android - 使用 JSON 执行 HttpPost 时无响应

java - 使用 SOAPUI 工具完成的 Web 服务测试是否可以完全在 Java 中完成?

c++ - 防止使用 ImpersonateNamedPipeClient()

java - 无法访问 0 以外的索引