CXF+WS-Security+Spring WebService服务器端+客户端及注意问题

项目中要用到webservice,刚听到的时候还挺开心的,因为我之前接触过,想来应该不是很难,。

谁料,事实不是这样的....,让我费了个好劲啊。

不说了,下面上代码,这是入门级的,所以会比较详细,仔细看:


服务器端:

       1、接口+实现类

       

//接口
package com.ekservice.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import com.ek.entry.user.User;

/** 
 * @author Administrator 
 * 类说明 
 */
@WebService(targetNamespace="http://jeeek-dp/", name="ExampleService")
public interface ExampleService {

	@WebResult(name="password")
	@WebMethod(action="http://jeeek-dp/ExampleService/getStr")
	public User getStr(@WebParam(name="name")String userName);
}
//实现类
package com.ekservice.impl;

import javax.jws.WebService;

import com.ek.entry.user.User;
import com.ekservice.service.ExampleService;

/** 
 * @author Administrator
 * 类说明 
 */
@WebService(targetNamespace="http://jeeek-dp/", serviceName="ExampleService", name="ExampleService")
public class ExampleServiceImpl implements ExampleService {

	public User getStr(String userName) {
		User user = new User();
		user.setAddress("北京市海淀区222号");
		user.setMobilePhone("010-1101111");
		return user;
	}

}
2、WS-Security 安全验证 - 过滤器

package com.ekservice.interceptor;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;

/** 
 * @author Administrator
 * 类说明 
 */
public class ExampleServiceInterceptor implements CallbackHandler{

	private Map passwords = new HashMap();
	
	public ExampleServiceInterceptor() {
		passwords.put("admin", "password");//此处的对应的是验证信息-用户名+密码,必须与客户端一致才可验证通过
	}
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
			String identifier = pc.getIdentifier();//用户名
			int usage = pc.getUsage();//验证方式
			if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
				if (!passwords.containsKey(identifier)) {
					try {
						throw new WSSecurityException("User not match - "+identifier);
					} catch (WSSecurityException e) {
						e.printStackTrace();
					}
				}
				// username token pwd...
				// ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同
				// 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
				// Changes片段
				pc.setPassword(passwords.get(identifier));// ▲【这里非常重要】▲
				// ▲PS 如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:
				// The
				// security token could not be authenticated or
				// authorized异常,服务端会认为客户端为非法调用
			}else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
				if (!passwords.containsKey(identifier)) {
					try {
						throw new WSSecurityException("User not match - "+identifier);
					} catch (WSSecurityException e) {
						e.printStackTrace();
					}
				}
				// set the password for client's keystore.keyPassword
				// ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同;
				// 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
				// Changes片段
				pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
				// ▲PS:如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:The
				// security token could not be authenticated or
				// authorized异常,服务端会认为客户端为非法调用
			}
		}
	}

}
3、Spring配置文件



	
	
	

        
	
	
	
        
        
        
        
			
			
			
			
				
					
						
						
						
						
					
				
			
		
		
			
		
	
	



4、User.java

package com.ek.entry.user;

import java.io.Serializable;
import java.util.Date;

/**
 * @包名   ek.entry.user.po
 * @文件名 User.java
 * @版本 V 1.0
 */
public class User implements Serializable{
	private static final long serialVersionUID = 1L;
	private int id;
	private String userName;	//用户名
	private String passWord;	//密码
	private String address;
	private String mobilePhone;
	private Date entryTime;		//录入时间
	private Date updateTime;	//更新时间
	private String entryUserId;	//录入人ID
	private String validFlag;	//有效标识
	private Integer access;
	/**
	 * @return the userName
	 */
	public String getUserName() {
		return userName;
	}
	/**
	 * @param userName the userName to set
	 */
	public void setUserName(String userName) {
		this.userName = userName;
	}
	/**
	 * @return the passWord
	 */
	public String getPassWord() {
		return passWord;
	}
	/**
	 * @param passWord the passWord to set
	 */
	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getMobilePhone() {
		return mobilePhone;
	}
	public void setMobilePhone(String mobilePhone) {
		this.mobilePhone = mobilePhone;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	/**
	 * @return the entryTime
	 */
	public Date getEntryTime() {
		return entryTime;
	}
	/**
	 * @param entryTime the entryTime to set
	 */
	public void setEntryTime(Date entryTime) {
		this.entryTime = entryTime;
	}
	/**
	 * @return the updateTime
	 */
	public Date getUpdateTime() {
		return updateTime;
	}
	/**
	 * @param updateTime the updateTime to set
	 */
	public void setUpdateTime(Date updateTime) {
		this.updateTime = updateTime;
	}
	/**
	 * @return the entryUserId
	 */
	public String getEntryUserId() {
		return entryUserId;
	}
	/**
	 * @param entryUserId the entryUserId to set
	 */
	public void setEntryUserId(String entryUserId) {
		this.entryUserId = entryUserId;
	}
	/**
	 * @return the validFlag
	 */
	public String getValidFlag() {
		return validFlag;
	}
	/**
	 * @param validFlag the validFlag to set
	 */
	public void setValidFlag(String validFlag) {
		this.validFlag = validFlag;
	}
	
	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}
	public User() {
		super();
		
		this.entryTime = new Date();
		this.updateTime = new Date();
		this.validFlag = "1";
	}
	/**
	 * @return the access
	 */
	public Integer getAccess() {
		return access;
	}
	/**
	 * @param access the access to set
	 */
	public void setAccess(Integer access) {
		this.access = access;
	}
	
}
至此,服务器端开发完成,启动tomcat即可访问接口,http://localhost:8080/jeeek-dp/services/ExampleService?wsdl


客户端:

        1、使用wsdl2java命令生成客户端代码,只保留生成的javabean跟接口即可,其他的文件可以全部删去,,我留下的文件。

         2、编写客户端接口访问验证拦截器,只要确保用户名密码与服务器相同即可(我的理解),代码:

package com.ek.client.interceptor;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;

/** 
 * @author 
 * 类说明 
 */
public class ExampleServiceClientInterceptor implements CallbackHandler{

	private Map passwords = new HashMap();
	
	public ExampleServiceClientInterceptor() {
		passwords.put("admin", "password");
	}
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
			String identifier = pc.getIdentifier();
			int usage = pc.getUsage();
			
			if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
				System.out.println(passwords.containsKey(identifier)+"="+passwords.get(identifier)+"-"+identifier);
				if (!passwords.containsKey(identifier)) {
					try {
						throw new WSSecurityException("User not match - "+identifier);
					} catch (WSSecurityException e) {
						e.printStackTrace();
					}
				}
				pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
			}else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
				if (!passwords.containsKey(identifier)) {
					try {
						throw new WSSecurityException("User not match - "+identifier);
					} catch (WSSecurityException e) {
						e.printStackTrace();
					}
				}
				pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
			}
		}
	}

}

3、客户端配置文件




	
	
	
		  
			
			
				
					
						
						
						
						
						
							
						
					
				
			
		
	
	

4、客户端调用接口:

package com.ek.client.call;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ek.client.services.example.ExampleService;
import com.ek.client.services.example.User;

/** 
 * @author 
 * 类说明 
 */
public class ExampleServiceClient {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cxf-client.xml");
		ExampleService es = (ExampleService) ctx.getBean("service");
		
		User u = es.getStr("ssss");
		
		System.out.println(u.getAddress);
	}
}

整个项目的包目录结构就不截图了,配置文件新建个src 文件放到里面即可,也可以直接放到src目录下。


因为整这个东西费了很多时间,坐下记录。



共勉!


你可能感兴趣的:(webservice,Spring)