網上看的CXF+ws-secutiry大多是通過配置相關的xml文件來進行服務端部署,這兒給出不一樣的做法。
web service接口及實現
package com.cxf.libraryServer; import javax.jws.WebMethod; @javax.jws.WebService public interface WebService { @WebMethod String serviceTest(); } package com.cxf.libraryServer; @javax.jws.WebService( name = "WebService", targetNamespace = "" ) public class WebServiceImpl implements WebService { @Override public String serviceTest() { return "success"; } }
服務端
1 package com.cxf.libraryServer.Server; 2 3 import com.cxf.libraryServer.WebService; 4 import com.cxf.libraryServer.WebServiceImpl; 5 import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor; 6 import org.apache.cxf.interceptor.LoggingInInterceptor; 7 import org.apache.cxf.interceptor.LoggingOutInterceptor; 8 import org.apache.cxf.jaxws.JaxWsServerFactoryBean; 9 import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; 10 11 import java.util.HashMap; 12 import java.util.Map; 13 14 public class WebServicePublish { 15 public static void main(String[] args) { 16 String address = "wsdl地址"; 17 //采用JDK方式進行發布 18 // Endpoint.publish(address, new WebServiceImpl()); 1920 21 //采用JaxWsServerFactoryBean方式 22 JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); 23 //服務發布地址 24 jaxWsServerFactoryBean.setAddress(address); 25 //提供服務類的類型 26 jaxWsServerFactoryBean.setServiceClass(WebService.class); 27 //提供服務的實例 28 jaxWsServerFactoryBean.setServiceBean(new WebServiceImpl()); 29 // 30 Map<String, Object> props = new HashMap<String, Object>(); 31 props.put("action", "UsernameToken"); 32 props.put("passwordType", "PasswordDigest"); 33 props.put("user", "cxfname"); 34 props.put("passwordCallbackClass", "com.cxf.libraryServer.Server.ServerPasswordCallback"); 35 WSS4JInInterceptor wss4jIn = new org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor(props); 36 // 37 jaxWsServerFactoryBean.getInInterceptors().add(wss4jIn); 38 jaxWsServerFactoryBean.getInInterceptors().add((new SAAJInInterceptor())); 39 jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor()); 40 jaxWsServerFactoryBean.getInInterceptors().add(new LoggingOutInterceptor()); 41 //發布服務 42 jaxWsServerFactoryBean.create(); 43 System.out.println("圖書館接口發布成功"); 44 } 45 }
服務端回調函數:用於驗證密碼
package com.libraryServer.Server; import org.apache.wss4j.common.ext.WSPasswordCallback; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.IOException; public class ServerPasswordCallback implements CallbackHandler { public void handle(Callback[] args) throws IOException,UnsupportedCallbackException { for (int i = 0; i < args.length; i++) { WSPasswordCallback pc = (WSPasswordCallback) args[i]; String identifier = pc.getIdentifier(); if ("cxfname".equals(identifier)) { pc.setPassword("admin"); } } } }
客戶端
package com.cxf.libraryServer.ClientTest; import com.cxf.libraryServer.WebService; import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import java.util.HashMap; import java.util.Map; public class Client { public WebService UserAccess() { try { String REMOTEDATA_CXF_NAME = "cxfname"; String REMOTEDATA_CXF_WSDL = "wsdl地址"; JaxWsProxyFactoryBean jwpFactory = new JaxWsProxyFactoryBean(); jwpFactory.setAddress(REMOTEDATA_CXF_WSDL); jwpFactory.setServiceClass(WebService.class); // Map<String, Object> outProps = new HashMap<String, Object>(); outProps.put("action", "UsernameToken"); outProps.put("user", REMOTEDATA_CXF_NAME); outProps.put("passwordType", "PasswordDigest"); outProps.put("passwordCallbackClass", "com.cxf.libraryServer.ClientTest.WSAuthHandler"); WSS4JOutInterceptor wss4jOut = new org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor(outProps); // jwpFactory.getOutInterceptors().add(wss4jOut); jwpFactory.getOutInterceptors().add(new SAAJOutInterceptor()); jwpFactory.getOutInterceptors().add(new LoggingOutInterceptor()); jwpFactory.getOutInterceptors().add(new LoggingInInterceptor()); return (WebService) jwpFactory.create(); } catch (Exception e) { e.printStackTrace(); } return null; } }
客戶端回調函數:用於發送密碼
package com.cxf.libraryServer.ClientTest; import org.apache.wss4j.common.ext.WSPasswordCallback; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.IOException; public class WSAuthHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; // 這里必須設置密碼,否則會拋出:java.lang.IllegalArgumentException: pwd == null // but a password is needed pc.setPassword("admin"); } } }
測試結果:在test層中測試
@Test public void myCXF_WebserviceTest(){ Client client = new Client(); WebService webService = client.UserAccess(); System.out.println(webService.serviceTest()); }
成功打印出:success

參考資料
Java code examples for org.apache.cxf.ws.ssecurity.wss4j.Wss4JOutInterceptor
淺談springmvc整合CXF+ws-security實現wbservice安全驗證
(ps:服務端發布是直接寫main來測試,在項目中可以直接寫個servlet來進行啟動cxf服務,詳細操作可以見:Java web項目啟動時,自動執行代碼的三種方式)
