如何在jax-ws请求中添加安全标头

问题描述:

我正在用apache cxf创建一个jax-ws客户端。 我正在努力与春季cotext配置。 所有我需要的是这头添加到我的SOAP请求:如何在jax-ws请求中添加安全标头

<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> 

我有三个参数:用户名令牌,密码登录。

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

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

使用此配置

<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); 
+0

嗨,我们为什么要检查用户?这是客户端的代码吗?看起来像服务器端的这个代码。我没有配置端点,我只想添加一个安全头并发送肥皂请求 – rastaman

+0

此代码用于客户端(请参阅jax-ws:client标记)。 out-interceptor在发送它之前拦截输出以添加标题。如果你不喜欢spring配置,请使用最后一个java示例。也许你发现提供密码的方式很奇怪,但它是CXF的默认设置 – pedrofb

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

所以你基本上需要定义(从CXF安全WSS4JOutInterceptor)一个新的拦截器bean并传递正确的键值输入到它的构造:

<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作为out拦截器分配给您的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,以检查是否添加了标题以稍微调整键/值。

+0

嗨。感谢您的回答。那么,我找到了一个类:UsernameTokenInterceptor它会解决我的问题。我怎么能在春天的环境中添加它? – rastaman