WebService:Axis客户端调用需要身份验证的CXF服务

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界面:

WebService:Axis客户端调用需要身份验证的CXF服务

 

cxf_server端和axis_client端的工程源码见附件。

 

你可能感兴趣的:(webservice)