標籤:cxf web services webservice
CXF中的攔截器分為in攔截器和out攔截器,又有用戶端攔截器和服務端攔截器。
攔截器使用流程:用戶端(out)-> 服務端(in)->處理業務->服務端(out)->用戶端(in),並不是每一步都需要攔截器。在這裡我們用到的是用戶端Out攔截器和服務端in攔截器。服務端in攔截器檢查使用者級許可權,用戶端out瀏覽器發送使用者資訊給服務端。
1、建立服務端驗證
JaxWsServerFactoryBean或Endpoint都可以通過getInInterceptors方法,向WebService服務添加攔截器。
1.1 Endpoint方式
HelloWorldService service = new HelloWorldServiceImpl();String address = "http://localhost:8080/hello";EndpointImpl endpoint = (EndpointImpl)Endpoint.publish(address, service);endpoint.getInInterceptors().add(new AuthInterceptor());
1.2 JaxWsServerFactoryBean方式
HelloWorldServiceImpl impl = new HelloWorldServiceImpl();JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();factory.setAddress("http://localhost:8080/hello");factory.setServiceClass(HelloWorldService.class);factory.setServiceBean(impl);factory.getInInterceptors().add(new AuthInterceptor());factory.create();
1.3 利用自訂攔截器實現許可權控制
自訂攔截去需要實現PhaseInterceptor介面,不過一般都是繼承自AbstractPhaseInterceptor<T>,下面我們來實現AuthInterceptor的許可權控制功能
package com.tiamaes.webservice.auth;import java.util.List;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.Element;import org.w3c.dom.NodeList;/** * <p>類描述:使用者權限驗證攔截器 </p> * <p>修改人:王成委 </p> * <p>修改時間:2014-5-10 下午03:16:16 </p> * @version */public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {//在調用之前攔截public AuthInterceptor() {super(Phase.PRE_INVOKE);}/** * 自訂攔截器需要實現handleMessage方法,該方法拋出Fault異常,可以自訂異常整合自Fault, * 也可以new Fault(new Throwable()) */public void handleMessage(SoapMessage soap) throws Fault {System.out.println("開始驗證使用者資訊");List<Header> headers = soap.getHeaders();//檢查headers是否存在if(headers == null | headers.size()<1){throw new Fault(new IllegalArgumentException("找不到Header,無法驗證使用者資訊"));}Header header = headers.get(0);Element el = (Element)header.getObject();NodeList users = el.getElementsByTagName("username");NodeList passwords = el.getElementsByTagName("password");//檢查是否有使用者名稱和密碼元素if(users.getLength()<1){throw new Fault(new IllegalArgumentException("找不到使用者資訊"));}String username = users.item(0).getTextContent().trim();if(passwords.getLength()<1){throw new Fault(new IllegalArgumentException("找不到密碼資訊"));}String password = passwords.item(0).getTextContent();//檢查使用者名稱和密碼是否正確if(!"admin".equals(username) || !"admin".equals(password)){throw new Fault(new IllegalArgumentException("使用者名稱或密碼不正確"));}else{System.out.println("使用者名稱密碼正確允許訪問");}}}
2、用戶端發送使用者資訊
用戶端則需要添加out攔截器,在out攔截器中加入訊息頭
用戶端攔截器:ClienLoginInterceptor
package com.tiamaes.webservice.auth;import java.util.List;import javax.xml.namespace.QName;import org.apache.cxf.binding.soap.SoapMessage;import org.apache.cxf.headers.Header;import org.apache.cxf.helpers.DOMUtils;import org.apache.cxf.interceptor.Fault;import org.apache.cxf.phase.AbstractPhaseInterceptor;import org.apache.cxf.phase.Phase;import org.w3c.dom.Document;import org.w3c.dom.Element;/** * <p>類描述: </p> * <p>修改記錄 ---------------- </p> * <p>修改人:王成委 </p> * <p>修改時間:2014-5-10 下午03:58:10 </p> * <p>修改備忘: </p> * @version */public class ClientLoginInterceptor extends AbstractPhaseInterceptor<SoapMessage> {private String username;private String password;public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}/** * 建立一個新的執行個體 ClientLoginInterceptor. * * @param username * @param password */public ClientLoginInterceptor(String username, String password) {super(Phase.PREPARE_SEND);this.username = username;this.password = password;}/* (non-Javadoc) * @see org.apache.cxf.interceptor.Interceptor#handleMessage(org.apache.cxf.message.Message) */public void handleMessage(SoapMessage soap) throws Fault {// TODO Auto-generated method stubList<Header> headers = soap.getHeaders();Document doc = DOMUtils.createDocument();Element auth = doc.createElement("authrity");Element username = doc.createElement("username");Element password = doc.createElement("password");username.setTextContent(this.username);password.setTextContent(this.password);auth.appendChild(username);auth.appendChild(password);//doc.appendChild(auth);headers.add(0, new Header(new QName("tiamaes"),auth));}}
用戶端添加ClientLoginInterceptor
public static void main(String[] args) {JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();Client client = dcf.createClient("http://127.0.0.1:8080/hello?wsdl");client.getOutInterceptors().add(new ClientLoginInterceptor("admin", "admin"));try {Object[] objs = client.invoke("syaHello", "Tom");System.out.println(objs[0].toString());} catch (Exception e) {e.printStackTrace();}}