在 CXF 3.0 和 Spring 中使用 Contract-First 启用 Police
Enable Police in CXF 3.0 and Spring with Contract-First
我正在尝试使用 CXF 3.1.0 和 Spring 4.1.6
在我的服务中实施 WS-Policy
我发现的大多数示例都是使用 CXF 2 的,并且像 cxf-extension-policy.xml 和 cxf-extension-ws-security.xml 这样的结构在 CXF 新版本中发生了变化。
我试过类似的方法:
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);
None 本作品。
有人知道如何使用 Spring 注释配置它吗?
好吧,我的问题不在 CXF/Spring 配置中...在部署时我预期的 WSDL 中。
我期待这样的事情:
<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 执行此操作时,我设置了身份验证类型、用户名和密码并正常工作。我只是不明白为什么我的政策没有出现
一段时间后,我发现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>
我会尝试这样加载外部策略:
InputStream is = this.getClass().getResourceAsStream(String filePath);
Map<String, Object> requestContext = ((BindingProvider)client).getRequestContext();
PolicyBuilder builder = bus.getExtension(org.apache.cxf.ws.policy.PolicyBuilder.class);
try {
Policy wsSecuritypolicy = builder.getPolicy(is);
requestContext.put(PolicyConstants.POLICY_OVERRIDE, wsSecuritypolicy);
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
requestContext.put(SecurityConstants.CALLBACK_HANDLER, MyCallBackClass.class.getName());
我正在尝试使用 CXF 3.1.0 和 Spring 4.1.6
在我的服务中实施 WS-Policy我发现的大多数示例都是使用 CXF 2 的,并且像 cxf-extension-policy.xml 和 cxf-extension-ws-security.xml 这样的结构在 CXF 新版本中发生了变化。
我试过类似的方法:
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);
None 本作品。
有人知道如何使用 Spring 注释配置它吗?
好吧,我的问题不在 CXF/Spring 配置中...在部署时我预期的 WSDL 中。
我期待这样的事情:
<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 执行此操作时,我设置了身份验证类型、用户名和密码并正常工作。我只是不明白为什么我的政策没有出现
一段时间后,我发现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>
我会尝试这样加载外部策略:
InputStream is = this.getClass().getResourceAsStream(String filePath);
Map<String, Object> requestContext = ((BindingProvider)client).getRequestContext();
PolicyBuilder builder = bus.getExtension(org.apache.cxf.ws.policy.PolicyBuilder.class);
try {
Policy wsSecuritypolicy = builder.getPolicy(is);
requestContext.put(PolicyConstants.POLICY_OVERRIDE, wsSecuritypolicy);
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
requestContext.put(SecurityConstants.CALLBACK_HANDLER, MyCallBackClass.class.getName());