ApacheCXF框架API实现了WS-Security协议,其中包括xml签名、用户令牌、时间戳等;
实现目标:在SOAP WebService的服务端实现客户端身份认证、时间戳形式的安全机制;(密钥加密及签名方式认证待续)
运行环境:apache-cxf-3.1.6、jdk1.7、tomcat7.0.68
cxf框架和spring高度集成,示例安全机制服务端基于spring框架,客户端调用可以使用或不使用spring框架;
对于客户端用户密码验证主要通过cxf框架的WSS4J拦截器实现,base64加密、解密过程本身由框架实现,用户只需要在服务端和客户端的拦截器实现方法中设置原始的用户名密码即可。
客户端发出请求前(请求出)拦截设置加密密码,服务端接收(请求入)后拦截解密验证密码。
服务端web.xml配置:
cxfjaxwssecurityserver1 contextConfigLocation WEB-INF/beans.xml org.springframework.web.context.ContextLoaderListener Apache CXF Endpoint cxf cxf org.apache.cxf.transport.servlet.CXFServlet 1 cxf /services/* 60
服务端spring bean配置:
服务端拦截器:
public class PasswdCallback implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback ) callbacks[0];
if(pc.getIdentifier().equals("administrator")){
pc.setPassword("merrick");
}else{
System.err.println("Password verified failed.");
}
}
}
Webservice接口类、实现类、实体类:
@WebService( name="BookService", portName="BookServicePort")
public interface BookService {
@WebMethod
public String getOneBookInfo(DTOBean param);
@WebMethod BookEntity getBookinfoEntity(DTOBean param);
}
public class BookServiceImpl implements BookService {
@Resource
WebServiceContext wsContext;
@Override
public String getOneBookInfo(DTOBean param) {
String bookinfo = "<>,2001,English";
System.out.println("---Invoking getOneBookInfo, DTOBean: "+ param.getId() + "," + param.getName());
return bookinfo;
}
@Override
public BookEntity getBookinfoEntity(DTOBean param) {
BookEntity be = new BookEntity();
be.setAuthor("Mark Twen");
be.setFirstpub("1778");
be.setName("Tom's house");
System.out.println("---Invoking getBookinfoEntity, DTOBean: "+ param.getId() + "," + param.getName());
return be;
}
}
public class BookEntity {
String name;
String author;
String firstpub;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getFirstpub() {
return firstpub;
}
public void setFirstpub(String firstpub) {
this.firstpub = firstpub;
}
}
客户端拦截器:
public class ClientPasswdCallback implements CallbackHandler {
private Map passwds = new HashMap();
public ClientPasswdCallback() {
passwds.put("administrator", "merrick");
}
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {//交给wss4j API去加密(ws-security的实现,用户令牌验证)
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback wsp = (WSPasswordCallback)callbacks[i];
String pas = passwds.get(wsp.getIdentifier());
if(pas!=null){
wsp.setPassword(pas);
return;
}
}
}
}
WebService 客户端调用(无框架方式、spring方式)(客户端略):
(webservice客户端可根据WebService的wsdl url,采用cxf的wsdl2java工具生成)
public static void clientwith_UserTokenAuth() throws Throwable {//success
/**
* 带用户令牌验证的客户端
* Spring配置
* **/
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "autoclient/test/client2.xml" });
// BookServiceImplService sv = new BookServiceImplService(u);
BookService client = (BookService) context.getBean("client");
DtoBean b = new DtoBean();
b.setId(1);
b.setName("a");
//
String response = client.getOneBookInfo(b);
System.out.println("Response: " + response);
BookEntity response2 = client.getBookinfoEntity(b);
System.out.println("Response: " + response2.getAuthor() + ", " + response2.getName() +", "+ response2.getFirstpub());
}
/***无框架方式*/
public static void clientwith_UserTokenAuth_withoutSpring() throws Throwable {//success
Map outProps = new HashMap();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN +" "+ WSHandlerConstants.TIMESTAMP);//令牌+时间戳
outProps.put(WSHandlerConstants.USER, "administrator" );
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST );
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, "autoclient.test.ClientPasswdCallback");
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(cxfclient.jaxws.auto.BookService.class);
// 设置ws访问地址
factory.setAddress("http://localhost:8080/cxfjaxwssecurityserver1/services/bookinfo");
factory.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
//addAll(list);
cxfclient.jaxws.auto.BookService service = (cxfclient.jaxws.auto.BookService) factory.create();
DtoBean b = new DtoBean();
b.setId(1);
b.setName("a");
String response = service.getOneBookInfo(b);
System.out.println(response);
}
客户端安全机制带框架方式调用,spring配置: