CXF服务端代码:
1、web.xml配置
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <!-- Spring Config Location -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/beans.xml</param-value>
- </context-param>
- <!-- Spring ContextLoaderListener -->
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <!-- Apache CXFServlet -->
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <servlet-class>
- org.apache.cxf.transport.servlet.CXFServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <!-- CXFServlet Mapping -->
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/service/*</url-pattern>
- </servlet-mapping>
- </web-app>
2、beans.xml配置, 在beans.xml中配置服务端的拦截器interceptor.AuthenticationInterceptor,拦截器需要
继承AbstractPhaseInterceptor
- <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.0.xsd
- http://cxf.apache.org/jaxws
- http://cxf.apache.org/schemas/jaxws.xsd">
- <!-- Import Apache CXF Bean Definition -->
- <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" />
- <!-- serviceClass指定接口 -->
- <jaxws:server id="hello"
- serviceClass="service.SampleWebService"
- address="/HelloWorld">
- <jaxws:serviceBean>
- <bean class="service.SampleWebService" />
- </jaxws:serviceBean>
- <jaxws:inInterceptors>
- <bean class="interceptor.AuthenticationInterceptor">
- <property name="username" value="admin" />
- <property name="password" value="admin" />
- </bean>
- </jaxws:inInterceptors>
- </jaxws:server>
- </beans>
3、在拦截器中对用户身份进行验证
- package interceptor;
- import java.util.List;
- import javax.xml.soap.SOAPException;
- import org.apache.cxf.binding.soap.SoapMessage;
- import org.apache.cxf.headers.Header;
- import org.apache.cxf.interceptor.Fault;
- import org.apache.cxf.phase.AbstractPhaseInterceptor;
- import org.apache.cxf.phase.Phase;
- import org.w3c.dom.Node;
- public class AuthenticationInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
- private String username;
- private String password;
- public AuthenticationInterceptor() {
- // 指定该拦截器在哪个阶段被激发
- super(Phase.PRE_INVOKE);
- }
- public void handleMessage(SoapMessage msg) throws Fault {
- List<Header> headers = msg.getHeaders();
- if (null == headers || headers.size() < 1) {
- throw new Fault(new SOAPException("SOAPHeader格式错误"));
- }
- for (Header header : headers) {
- Node root = (Node) header.getObject();
- if("Authentication".equals(root.getNodeName())){
- Node userNode = root.getFirstChild();
- Node passwordNode = root.getLastChild();
- if(userNode == null || passwordNode == null){
- throw new Fault(new SOAPException("SOAPHeader需要包含Username和Password节点"));
- }
- if(!userNode.getNodeName().equals("Username") || !passwordNode.getNodeName().equals("Password")){
- throw new Fault(new SOAPException("SOAPHeader需要包含Username和Password节点"));
- }
- if(username.equals(userNode.getTextContent()) && password.equals(passwordNode.getTextContent())){
- System.out.println("认证通过");
- }
- else{
- throw new Fault(new SOAPException("用户名或密码错误"));
- }
- }
- else{
- throw new Fault(new SOAPException("SOAPHeader需要包含Authentication节点"));
- }
- }
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
4、服务接口,CXF可以直接发布JavaBean,只需要一个@WebService注解
- package service;
- import javax.jws.WebService;
- @WebService
- public class SampleWebService{
- public String sayHello(String name) {
- return "Hello, "+name;
- }
- public String sayHi(String name) {
- return "Hi, "+name;
- }
- }
5、Axis客户端:
- /**
- * <soapenv:Header>
- * <Authentication
- * soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
- * soapenv:mustUnderstand="0"
- * xmlns="">
- * <Username>admin</Username>
- * <Password>admin</Password>
- * </Authentication>
- * </soapenv:Header>
- * @param user
- * @param password
- */
- public static void authentication(String user, String password){
- try {
- Call call = (Call)new Service().createCall();
- call.setTargetEndpointAddress("http://localhost:8080/ws/service/HelloWorld");
- String namespace = "";//命名空间
- SOAPHeaderElement header = new SOAPHeaderElement(namespace,"Authentication");
- header.setPrefix("");//前缀
- header.addChildElement("Username").addTextNode(user);
- header.addChildElement("Password").addTextNode(password);
- call.addHeader(header);
- Object obj = call.invoke("sayHi", new String[]{"sam"});
- System.out.println(obj);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
在axis的jar包中还提供了一个tcp_moniter,可以用来拦截soap消息,便于debug。
可以使用java -Djava.ext.dirs=lib org.apache.axis.utils.tcpmon来启动,启动前要先将axis的jar包都放在lib目录下,然后在lib的同级目录中建一个bat脚本,脚本中写:java -Djava.ext.dirs=lib org.apache.axis.utils.tcpmon。
这样双击bat脚本就可以启动tcp_moniter了。
tcp_moniter界面:
cxf_server端和axis_client端的工程源码见附件。