您好,登錄后才能下訂單哦!
Apache CXF中如何創建安全的Web Service,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
我們在使用Web Service的過程中,很多情況是需要對web service請求做認證的,對于運行在web容器里的應用程序來說,可能會比較簡單一些,通常可以通過filter來做一些處理,但是其實CXF本身也提供了對web service認證的方式。下面來看一下如何實現。
1. 首先是一個簡單pojo
package com.googlecode.garbagecan.cxfstudy.security; public class User { private String id; private String name; private String password; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
2. Web Service接口
package com.googlecode.garbagecan.cxfstudy.security; import java.util.List; import javax.jws.WebMethod; import javax.jws.WebResult; import javax.jws.WebService; @WebService public interface UserService { @WebMethod @WebResult List<User> list(); }
3. Web Service實現類
package com.googlecode.garbagecan.cxfstudy.security; import java.util.ArrayList; import java.util.List; public class UserServiceImpl implements UserService { public List<User> list() { List<User> users = new ArrayList<User>(); for (int i = 0; i < 10; i++) { User user = new User(); user.setId("" + i); user.setName("user_" + i); user.setPassword("password_" + i); users.add(user); } return users; } }
4. Server端Handler,其中使用了一個Map來存放用戶信息,真是應用中可以使用數據庫或者其它方式獲取用戶和密碼
package com.googlecode.garbagecan.cxfstudy.security; 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; public class ServerUsernamePasswordHandler implements CallbackHandler { // key is username, value is password private Map<String, String> users; public ServerUsernamePasswordHandler() { users = new HashMap<String, String>(); users.put("admin", "admin"); } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback callback = (WSPasswordCallback) callbacks[0]; String id = callback.getIdentifier(); if (users.containsKey(id)) { if (!callback.getPassword().equals(users.get(id))) { throw new SecurityException("Incorrect password."); } } else { throw new SecurityException("Invalid user."); } } }
5. Client端Handler,用來設置用戶密碼,在真實應用中可以根據此類和下面的測試類來修改邏輯設置用戶名和密碼。
package com.googlecode.garbagecan.cxfstudy.security; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class ClientUsernamePasswordHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback callback = (WSPasswordCallback) callbacks[0]; int usage = callback.getUsage(); System.out.println("identifier: " + callback.getIdentifier()); System.out.println("usage: " + callback.getUsage()); if (usage == WSPasswordCallback.USERNAME_TOKEN) { callback.setPassword("admin"); } } }
6. 單元測試類,注意在Server端添加了WSS4JInInterceptor到Interceptor列表中,在Client添加了WSS4JOutInterceptor到Interceptor列表中。
package com.googlecode.garbagecan.cxfstudy.security; import java.net.SocketTimeoutException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.ws.WebServiceException; import junit.framework.Assert; import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import org.apache.ws.security.WSConstants; import org.apache.ws.security.handler.WSHandlerConstants; import org.junit.BeforeClass; import org.junit.Test; public class UserServiceTest { private static final String address = "http://localhost:9000/ws/security/userService"; @BeforeClass public static void setUpBeforeClass() throws Exception { JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean(); factoryBean.getInInterceptors().add(new LoggingInInterceptor()); factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); Map<String, Object> props = new HashMap<String, Object>(); props.put("action", "UsernameToken"); props.put("passwordType", "PasswordText"); props.put("passwordCallbackClass", ServerUsernamePasswordHandler.class.getName()); WSS4JInInterceptor wss4JInInterceptor = new WSS4JInInterceptor(props); factoryBean.getInInterceptors().add(wss4JInInterceptor); factoryBean.setServiceClass(UserServiceImpl.class); factoryBean.setAddress(address); factoryBean.create(); } @Test public void testList() { JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean(); factoryBean.setAddress(address); factoryBean.setServiceClass(UserService.class); Object obj = factoryBean.create(); Client client = ClientProxy.getClient(obj); Endpoint endpoint = client.getEndpoint(); Map<String,Object> props = new HashMap<String,Object>(); props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); props.put(WSHandlerConstants.USER, "admin"); props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientUsernamePasswordHandler.class.getName()); WSS4JOutInterceptor wss4JOutInterceptor = new WSS4JOutInterceptor(props); endpoint.getOutInterceptors().add(wss4JOutInterceptor); HTTPConduit conduit = (HTTPConduit) client.getConduit(); HTTPClientPolicy policy = new HTTPClientPolicy(); policy.setConnectionTimeout(5 * 1000); policy.setReceiveTimeout(5 * 1000); conduit.setClient(policy); UserService service = (UserService) obj; try { List<User> users = service.list(); Assert.assertNotNull(users); Assert.assertEquals(10, users.size()); } catch(Exception e) { if (e instanceof WebServiceException && e.getCause() instanceof SocketTimeoutException) { System.err.println("This is timeout exception."); } else { e.printStackTrace(); } } } }
***運行上面的測試類來測試結果,也可以修改測試方法中的密碼,看看錯誤結果,這里就不在寫錯誤密碼的測試用例了。
看完上述內容,你們掌握Apache CXF中如何創建安全的Web Service的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。