通过合同优先启用CXF 3.0和Spring的警察

时间:2015-05-14 19:33:02

标签: spring web-services wsdl cxf ws-security

我正在尝试使用CXF 3.1.0和Spring 4.1.6在我的服务中实现WS-Policy

我发现的大多数示例都是使用CXF 2,并且在CXF新版本中更改了cxf-extension-policy.xml和cxf-extension-ws-security.xml等结构。

我尝试过类似的事情:

package spring;

import java.util.LinkedList;
import java.util.List;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.feature.AbstractFeature;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.ws.policy.WSPolicyFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

import com.student.StudentService;
import com.student.service.StudentServiceImpl;

@Configuration
@ImportResource({"classpath:META-INF/cxf/cxf.xml"})
public class CXFConfig {

@Autowired
private Bus cxfBus;

@Bean
public StudentService service(){
    return new StudentServiceImpl();
}

@Autowired
@Bean
public Endpoint serviceImpl(
        final StudentService service){

    EndpointImpl endpoint = new EndpointImpl(this.cxfBus, service);
    endpoint.setAddress("/StudentService");
    endpoint.publish();

    return endpoint;
}
}

我的WSDL有一些策略,基本上是来自this tutorial

的WSDL

我使用Contract-first生成我的Java类。

当我运行项目时,我的政策不会出现。

我试过

final Map<String, Object> properties = new HashMap<>();
properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
properties.put(WSHandlerConstants.PW_CALLBACK_REF, ServerPasswordCallback.class.getName());

EndpointImpl endpoint = new EndpointImpl(this.cxfBus, portType);
endpoint.setProperties(properties);
endpoint.setAddress("/StudentService");
endpoint.publish();

return endpoint;

我也试过

final Map<String, Object> properties = new HashMap<>();
properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
properties.put(WSHandlerConstants.PW_CALLBACK_REF, ServerPasswordCallback.class.getName());

cxfBus.getFeatures().add(new WSPolicyFeature());
cxfBus.getInInterceptors().add(new WSS4JInInterceptor(properties));

EndpointImpl endpoint = new EndpointImpl(this.cxfBus, portType);
endpoint.setAddress("/StudentService");
endpoint.publish();

return endpoint;

WSPolicyFeature wsPolicyFeature = new WSPolicyFeature();
wsPolicyFeature.initialize(this.cxfBus);

这些都不起作用。

有人知道如何使用Spring注释配置它吗?

3 个答案:

答案 0 :(得分:2)

过了一会儿,我发现WSS4J使用拦截器的概念而不是合同中的策略。

我将我的spring实现改为

    EndpointImpl endpoint = new EndpointImpl(this.cxfBus, flightService);
    endpoint.setAddress("/FlightService");
    endpoint.setWsdlLocation("src/main/resources/wsdls/flightservice_v1r1.wsdl");
    endpoint.getProperties().put("ws-security.callback-handler", new ServerPasswordCallback());
    endpoint.publish();

然而,即使我在部署合同时使用了该配置,它也显示了2个wsdl:binding和2个wsdl:service ...

我找到了解决问题的方法,而不是第一种解决方案,我将我的政策外部化为XML文件并使用

来激活我的服务
@Policies({
  @Policy(uri="classpath:policies/usernameToken.xml", includeInWSDL=true)
})

我的Spring配置已缩减为

EndpointImpl endpoint = new EndpointImpl(this.cxfBus, new FlightServiceImpl());
endpoint.setAddress("/FlightService");
endpoint.getProperties().put("ws-security.callback-handler", new ServerPasswordCallback());
endpoint.publish();

当我部署项目时,我终于看到了

<wsdl:service name="FlightServiceImplService">
  <wsdl:port binding="tns:FlightServiceImplServiceSoapBinding" name="FlightServiceImplPort">
    <soap:address location="http://localhost:8080/ws-security/FlightService"/>
  </wsdl:port>
  <wsp:PolicyReference URI="#authenticationPolicy"/>
</wsdl:service>

答案 1 :(得分:0)

好吧,我的问题不是在CXF / Spring配置中...在WSDL中我是在depoy时预期的。

我期待这样的事情:

<wsdl:binding name="ChangeStudentDetailsImplServiceSoapBinding" type="tns:ChangeStudentDetails">
  <wsp:PolicyReference URI="#ChangeStudentDetailsImplServiceSoapBindingPolicy"/>
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name="changeName">
    <soap:operation soapAction="" style="document"/>
    <wsdl:input name="changeName">
      <soap:body use="literal"/>
    </wsdl:input>
    <wsdl:output name="changeNameResponse">
      <soap:body use="literal"/>
    </wsdl:output>
  </wsdl:operation>
</wsdl:binding>

<wsdl:service name="ChangeStudentDetailsImplService">
  <wsdl:port binding="tns:ChangeStudentDetailsImplServiceSoapBinding" name="ChangeStudentDetailsImplPort">
    <wsp:PolicyReference URI="#ChangeStudentDetailsImplServiceSoapBindingPolicy"/>
    <soap:address location="http://localhost:8080/ws-policy/ChangeStudent"/>
  </wsdl:port>
</wsdl:service>

然而,当我使用契约优先方法时,我收到了:

<wsdl:binding name="ChangeStudentDetailsImplServiceSoapBinding" type="tns:ChangeStudentDetails">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name="changeName">
    <soap:operation soapAction="" style="document"/>
    <wsdl:input name="changeName">
      <soap:body use="literal"/>
    </wsdl:input>
    <wsdl:output name="changeNameResponse">
      <soap:body use="literal"/>
    </wsdl:output>
  </wsdl:operation>
</wsdl:binding>

<wsdl:service name="ChangeStudentDetailsImplService">
  <wsdl:port binding="tns:ChangeStudentDetailsImplServiceSoapBinding" name="ChangeStudentDetailsImplPort">
    <soap:address location="http://localhost:8080/ws-policy/ChangeStudent"/>
  </wsdl:port>
</wsdl:service>

所以我觉得那不行。

我将CXF / Spring配置更改为

@Autowired
@Bean
public Endpoint serviceImpl(
        final ChangeStudentDetails portType){

    Map<String, Object> inProps = new HashMap<String, Object>();
    inProps.put("action", "UsernameToken");
    inProps.put("passwordType", "PasswordText");
    inProps.put("passwordCallbackClass", ServerPasswordCallback.class.getName());

    EndpointImpl endpoint = new EndpointImpl(this.cxfBus, portType);
    endpoint.getInInterceptors().add(new WSS4JInInterceptor(inProps));
    endpoint.setAddress("/StudentService");
    endpoint.publish();

    return endpoint;
}

当我通过SOAPUI执行此操作时,我设置了身份验证的类型,用户名和密码并且正常工作。我只是不明白为什么我的政策没有出现

答案 2 :(得分:0)

我会尝试这样的东西加载外部政策:

{ %load static %}