2

我正在使用 apache cxf 创建一个 jax-ws 客户端。我正在为 spring cotext 配置而苦苦挣扎。我只需要将此标头添加到我的肥皂请求中:

<soapenv:Header>
  <wsse:Security  xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
     <wsse:UsernameToken wsu:Id="usernametoken">
        <wsse:Username>login</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>        
     </wsse:UsernameToken>
  </wsse:Security>

我有三个参数:usernametoken、password、login。

    <jaxws:client id="***" name="***"
              endpointName="***"
              serviceName="***"
              address="***"
              serviceClass="***"
              username="***"
              password="***"
              xmlns:tns="***">
</jaxws:client>

上面的代码工作并发送肥皂消息,但没有安全头!你能给我一些想法如何添加那个标题吗?

4

2 回答 2

5

使用此配置

<jaxws:client   etc...>
      <jaxws:outInterceptors>     
       <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
          <constructor-arg>
              <map>
                  <entry key="action" value="UsernameToken"/>
                  <entry key="user" value="login"/>
                  <entry key="passwordType" value="PasswordText"/>
                  <entry key="passwordCallbackRef" value-ref="myPasswordCallback"/>
               </map>
           </constructor-arg>
        </bean>
      </jaxws:outInterceptors>
   </jaxws:client>

   <bean id="myPasswordCallback" class="client.ClientPasswordCallback"/>

而这个类来管理密码

public class ClientPasswordCallback implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, 
            UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        if ("login".equals(pc.getIdentifier())) {
            pc.setPassword("thepassword");
        } // else {...} - can add more users, access DB, etc.
    }
}

如果你更喜欢 Java 代码,也是可以的

Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put("action", "UsernameToken");
outProps.put("user", "login");
outProps.put("passwordType","PasswordText");
ClientPasswordCallback c = new ClientPasswordCallback();
outProps.put("passwordCallbackRef",c);

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
于 2016-06-01T12:49:35.213 回答
2

您需要使用 CXF 拦截器添加安全标头。

因此,您基本上需要定义一个新的拦截器 bean(来自 cxf-security 的WSS4JOutInterceptor)并将正确的键值作为输入传递给它的构造函数:

<bean id="fooSecurityOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
    <constructor-arg>
        <map>
        [...]
        </map>
    </constructor-arg>
</bean>

请注意,这记录在http://cxf.apache.org/docs/ws-security.html但您可能需要查看 org.apache.ws.security.handler.WSHandlerConstants 的源代码以获取所有可能的密钥(在您的情况下,请查看 USERNAME_TOKEN、PASSWORD_TYPE ...)并将您的值注入此 bean 中的相应键。

然后,您只需将此 bean 作为输出拦截器分配给您的 jaxws-client bean。

<jaxws:client id="***" name="***" endpointName="***" serviceName="***" address="***" serviceClass="***" xmlns:tns="***">
    <jaxws:outInterceptors>
        <ref bean="fooSecurityOutInterceptor" />
    </jaxws:outInterceptors>
</jaxws:client>

这应该够了吧。您可以添加第二个输出拦截器,例如org.apache.cxf.interceptor.LoggingOutInterceptor以检查是否添加了标头以稍微调整键/值。

于 2016-05-31T16:25:58.670 回答