使用apache加密用户名令牌cxf

时间:2016-05-31 15:16:16

标签: cxf wss4j usernametoken

问候好人。

我有一个我想要使用的肥皂网服务。我创建了一个小项目来模拟实际项目中需要的内容,尤其是用户名令牌加密。

如下所示,有关如何在客户端加密密码的步骤:

  • 写下未加密的密码值。
  • 然后,使用密码密钥证书的公共部分加密在步骤1中创建的数据块。使用RSA算法,并使用PKCS#1.5填充(不是OAEP),并将结果添加到加密流中 - 这将成为通过API提交的加密密码。
  • 使用base64编码将生成的加密字节数组转换为字符串。在API请求中将此base64编码的字符串作为启动程序SecurityCredential值提供。
  • 使用公开密钥加密的密码,该公钥来自发给发起人的X509证书,专门用于此目的。

到目前为止,我已经能够创建客户端和服务器,并且我能够发送请求并获得响应。

我还能够通过在ClientPasswordCallback类中传递带有密码的用户名令牌作为纯文本并在ServerPasswordCallback类中检查这些证书来保护Web服务。

我已经进一步采用单独的请求使用 wss4j RSA X509 加密邮件的正文部分,我公开了存储在clientKey.jks中的密钥和存储在privateKey.jks中的私钥,并通过在客户端和服务器密码回调处理程序中提供适当的密码,我已经能够在客户端加密正文部分并在服务器上解密它。

挑战:我遇到的主要挑战是将上述两个步骤合并到一个请求中,以便使用公钥,我可以加密密码用户名令牌,并使用私钥在服务器端解密。

NB 我已经使用jdk附带的keygen工具生成了测试密钥。

我想象ClientPasswordCallback类中将有两个密码,一个用于clientKey.jks密钥库,另一个密码需要加密。

这是我迄今为止能够存档的内容:

客户端

TestMathUtility类

public static void main(String[] args) {

    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

    // Use the URL defined in the soap address portion of the WSDL
    factory.setAddress("http://localhost:8080/MathUtility/services/MathUtilityPort");

    // Utilize the class which was auto-generated by Apache CXF wsdl2java
    factory.setServiceClass(MathUtility.class);

    Object client = factory.create();

    // Adding Logging Interceptors
    LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
    loggingOutInterceptor.setPrettyLogging(true);
    ClientProxy.getClient(client).getOutInterceptors().add(loggingOutInterceptor);

    LoggingInInterceptor loggingInInterceptor = new LoggingInInterceptor();
    loggingInInterceptor.setPrettyLogging(true);
    ClientProxy.getClient(client).getInInterceptors().add(loggingInInterceptor);

    // Set up WS-Security Encryption
    // Reference: https://ws.apache.org/wss4j/using.html
    Map<String, Object> props = new HashMap<String, Object>();
    props.put(WSHandlerConstants.USER, "testkey");
    props.put(WSHandlerConstants.ACTION, WSHandlerConstants.ENCRYPT);
    props.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
    props.put(WSHandlerConstants.ENC_PROP_FILE, "clientKeystore.properties");
    props.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");
    props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());

    WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(props);

    ClientProxy.getClient(client).getOutInterceptors().add(wss4jOut);

    try {

        // Call the Web Service to perform an operation
        int response = ((MathUtility)client).addIntegers(5, 10);

        System.out.println("Response we've got ========= "+response);

      } catch (SecurityException e) {
        e.printStackTrace();
      } catch (IllegalArgumentException e) {
        e.printStackTrace();
      }

}

ClientPasswordCallback类

public class ClientPasswordCallback implements CallbackHandler {

@Override
public void handle(Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {

    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

    // set the password for our message.
    pc.setPassword("clientstorepass");

}

}

服务器端

MathUtility类

@WebService(targetNamespace = "http://utility.math.com/", portName =      "MathUtilityPort", serviceName = "MathUtilityService")
public class MathUtility {

public int addIntegers(int firstNum, int secondNum) {
    return firstNum + secondNum;
}

public int factorial(int n) {
    int result = 1;

    for (int i = 1; i <= n; i++) {
        result = result * i;
    }

    return result;
}
}

ServerPasswordCallback类

public class ServerPasswordCallback implements CallbackHandler {

@Override
public void handle(Callback[] arg0) throws IOException,
        UnsupportedCallbackException {

    WSPasswordCallback pc = (WSPasswordCallback) arg0[0];

    // set the password for our message.
    pc.setPassword("storepass");

}

}

CXF-beans.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<bean id="myPasswordCallback" class="com.math.utility.security.ServerPasswordCallback"/>

<jaxws:endpoint xmlns:tns="http://utility.math.com/" id="mathutility"
    implementor="com.math.utility.MathUtility" wsdlLocation="wsdl/mathutility.wsdl"
    endpointName="tns:MathUtilityPort" serviceName="tns:MathUtilityService"
    address="/MathUtilityPort">
    <jaxws:features>
        <bean class="org.apache.cxf.feature.LoggingFeature" />
    </jaxws:features>

        <jaxws:inInterceptors>
          <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
             <constructor-arg>
                <map>
                   <entry key="user" value="testkey"/>
                   <entry key="action" value="Encrypt"/>
                   <entry key="passwordType" value="PasswordText"/>
                   <entry key="decryptionParts" value="{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body"/>
                   <entry key="decryptionPropFile" value="serverKeystore.properties"/>
                   <entry key="passwordCallbackRef">
                      <ref bean="myPasswordCallback"/>
                   </entry>
                </map>
             </constructor-arg>
          </bean>

       </jaxws:inInterceptors>

</jaxws:endpoint>

clientKeyStore.properties文件在服务器端使用相同的结构

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.file=clientkeystore.jks
org.apache.ws.security.crypto.merlin.keystore.password=clientstorepass
org.apache.ws.security.crypto.merlin.keystore.type=jks

尚未提供使用的.jks文件

NB 我没有使用弹簧。

2 个答案:

答案 0 :(得分:0)

如果您想要自定义摘要,可以覆盖方法verifyCustomPassword(UsernameToken usernameToken, RequestData data) in UsernameTokenValidator

要将它连接到您的网络服务,请查看我对另一个SO-question的回答。这个答案的要点是:

<property name="wssConfig">
        <ref bean="usernameTokenWssConfig"/>
</property>

并将引用的类添加到您的代码库中:

@Component("usernameTokenWssConfig")
public class UsernameTokenWssConfig extends WSSConfig {
    public UsernameTokenWssConfig() {
        setValidator(WSSecurityEngine.USERNAME_TOKEN, new CustomUsernameTokenValidator());
        setRequiredPasswordType(WSConstants.CUSTOM_TOKEN );
    }
}

答案 1 :(得分:0)

这就是我使用加密部分对UT进行加密的方式

outProps.put(WSHandlerConstants.ENCRYPTION_PARTS,"{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" );

为了用加密部分加密用户名令牌。在第二个花括号内添加 SOAP 标头命名空间

我得到了一个像下面这样的加密 UT(我只加密了内容,只有你可以根据需要做元素)

<wsse:UsernameToken
                wsu:Id="UsernameToken-99bea96d-c6ef-444c-aa8a-ec807f58aa0c">
                <xenc:EncryptedData
                    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                    Id="ED-59f84d2b-3195-436f-b8f4-513fea23c00a"
                    Type="http://www.w3.org/2001/04/xmlenc#Content">
                    <xenc:EncryptionMethod
                        Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
                    <ds:KeyInfo
                        xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                        <wsse:SecurityTokenReference
                            xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                            xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"
                            wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
                            <wsse:Reference
                                URI="#EK-748c3d27-f6be-4b81-b864-87bc6457e247" />
                        </wsse:SecurityTokenReference>
                    </ds:KeyInfo>
                    <xenc:CipherData>
                        <xenc:CipherValue>wSZsu9LR6q9fpUPYYF5GSA7T/3iZWMd0cB/80Z33DThzCB0kqnupGETVmGfVQheGUc3O+/B4X7i70aMTyOo5u0fIqa4kwrlKZBe9he359mpgakKgC4wOb65sDThT1fH4PvY6TSBjIOJ0T5jIyt1pGwacRLzmvFxxHxr3qfAOf27LLGJ0P0eAKchE19nAkfP+Tc2GbAkcxi/4SDQ7bBWVaveRgSET0dpheooBGORtt4VJ/dyMwogupAyJKoiqe3RFRCvsmK/UtkVGQYh/W14ei/s7G3mVAch8fQZXCS8jcEaqzkDaNzrZo8+IjJFgrPQY23g3fp57QXIDB84NNUhsm7NHXMNfAq7x97kng+Qwke6uqHcMPjGI9boKw/wZmhipYstFzUpOpF86W9FwcJPyTFR58jvdnX5OGJ1wFbFdI9cAjWdncIEmnOTl69pKRmGmbJYj7Ie43q+eNH/1+2RawBRhZG43VLZL5C7ydFu0xJ2DsD4nacvDfH0i8tcMCHyHkWf2po9Y/dBtS2kWAxfNxWQNvI1BceumsMvpSzK7WjXPJ/vaKlMoSQJtsBxg9RhA
                        </xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedData>
            </wsse:UsernameToken>