Apache CXF实战之六 创建安全的Web Service

我们在使用Web Service的过程中,很多情况是需要对web service请求做认证的,对于运行在web容器里的应用程序来说,可能会比较简单一些,通常可以通过filter来做一些处理,但是其实CXF本身也提供了对web service认证的方式。下面来看一下如何实现

1. 首先是一个简单pojo

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_1 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. public class User {  

  4.     private String id;  

  5.     private String name;  

  6.     private String password;  

  7.     public String getId() {  

  8.         return id;  

  9.     }  

  10.     public void setId(String id) {  

  11.         this.id = id;  

  12.     }  

  13.     public String getName() {  

  14.         return name;  

  15.     }  

  16.     public void setName(String name) {  

  17.         this.name = name;  

  18.     }  

  19.     public String getPassword() {  

  20.         return password;  

  21.     }  

  22.     public void setPassword(String password) {  

  23.         this.password = password;  

  24.     }  

  25. }  

2. Web Service接口

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_2 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. import java.util.List;  

  4.   

  5. import javax.jws.WebMethod;  

  6. import javax.jws.WebResult;  

  7. import javax.jws.WebService;  

  8.   

  9. @WebService   

  10. public interface UserService {  

  11.     @WebMethod  

  12.     @WebResult List<User> list();  

  13.   

  14. }  

3. Web Service实现类

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_3 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. import java.util.ArrayList;  

  4. import java.util.List;  

  5.   

  6. public class UserServiceImpl implements UserService {  

  7.   

  8.     public List<User> list() {  

  9.         List<User> users = new ArrayList<User>();  

  10.         for (int i = 0; i < 10; i++) {  

  11.             User user = new User();  

  12.             user.setId("" + i);  

  13.             user.setName("user_" + i);  

  14.             user.setPassword("password_" + i);  

  15.             users.add(user);  

  16.         }  

  17.         return users;  

  18.     }  

  19.   

  20. }  

4. Server端Handler,其中使用了一个Map来存放用户信息,真是应用中可以使用数据库或者其它方式获取用户和密码

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_4 name=ZeroClipboardMovie_4 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=4&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. import java.io.IOException;  

  4. import java.util.HashMap;  

  5. import java.util.Map;  

  6.   

  7. import javax.security.auth.callback.Callback;  

  8. import javax.security.auth.callback.CallbackHandler;  

  9. import javax.security.auth.callback.UnsupportedCallbackException;  

  10.   

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

  12.   

  13. public class ServerUsernamePasswordHandler implements CallbackHandler {  

  14.   

  15.     // key is username, value is password  

  16.     private Map<String, String> users;  

  17.   

  18.     public ServerUsernamePasswordHandler() {  

  19.         users = new HashMap<String, String>();  

  20.         users.put("admin""admin");  

  21.     }  

  22.   

  23.     public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {  

  24.         WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];  

  25.         String id = callback.getIdentifier();  

  26.         if (users.containsKey(id)) {  

  27.             if (!callback.getPassword().equals(users.get(id))) {  

  28.                 throw new SecurityException("Incorrect password.");  

  29.             }  

  30.         } else {  

  31.             throw new SecurityException("Invalid user.");  

  32.         }  

  33.     }  

  34. }  

5. Client端Handler,用来设置用户密码,在真实应用中可以根据此类和下面的测试类来修改逻辑设置用户名和密码。

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_5 name=ZeroClipboardMovie_5 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=5&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. import java.io.IOException;  

  4.   

  5. import javax.security.auth.callback.Callback;  

  6. import javax.security.auth.callback.CallbackHandler;  

  7. import javax.security.auth.callback.UnsupportedCallbackException;  

  8.   

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

  10.   

  11. public class ClientUsernamePasswordHandler implements CallbackHandler {  

  12.     public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {  

  13.         WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];  

  14.         int usage = callback.getUsage();  

  15.         System.out.println("identifier: " + callback.getIdentifier());  

  16.         System.out.println("usage: " + callback.getUsage());  

  17.         if (usage == WSPasswordCallback.USERNAME_TOKEN) {  

  18.             callback.setPassword("admin");  

  19.         }  

  20.     }  

  21. }  

6. 单元测试类,注意在Server端添加了WSS4JInInterceptor到Interceptor列表中,在Client添加了WSS4JOutInterceptor到Interceptor列表中。

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_6 name=ZeroClipboardMovie_6 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=6&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. package com.googlecode.garbagecan.cxfstudy.security;  

  2.   

  3. import java.net.SocketTimeoutException;  

  4. import java.util.HashMap;  

  5. import java.util.List;  

  6. import java.util.Map;  

  7.   

  8. import javax.xml.ws.WebServiceException;  

  9.   

  10. import junit.framework.Assert;  

  11.   

  12. import org.apache.cxf.endpoint.Client;  

  13. import org.apache.cxf.endpoint.Endpoint;  

  14. import org.apache.cxf.frontend.ClientProxy;  

  15. import org.apache.cxf.interceptor.LoggingInInterceptor;  

  16. import org.apache.cxf.interceptor.LoggingOutInterceptor;  

  17. import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;  

  18. import org.apache.cxf.jaxws.JaxWsServerFactoryBean;  

  19. import org.apache.cxf.transport.http.HTTPConduit;  

  20. import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;  

  21. import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;  

  22. import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;  

  23. import org.apache.ws.security.WSConstants;  

  24. import org.apache.ws.security.handler.WSHandlerConstants;  

  25. import org.junit.BeforeClass;  

  26. import org.junit.Test;  

  27.   

  28. public class UserServiceTest {  

  29.   

  30.     private static final String address = "http://localhost:9000/ws/security/userService";  

  31.       

  32.     @BeforeClass  

  33.     public static void setUpBeforeClass() throws Exception {  

  34.         JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();  

  35.         factoryBean.getInInterceptors().add(new LoggingInInterceptor());  

  36.         factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());  

  37.   

  38.         Map<String, Object> props = new HashMap<String, Object>();  

  39.         props.put("action""UsernameToken");  

  40.         props.put("passwordType""PasswordText");  

  41.         props.put("passwordCallbackClass", ServerUsernamePasswordHandler.class.getName());  

  42.         WSS4JInInterceptor wss4JInInterceptor = new WSS4JInInterceptor(props);  

  43.         factoryBean.getInInterceptors().add(wss4JInInterceptor);  

  44.           

  45.         factoryBean.setServiceClass(UserServiceImpl.class);  

  46.         factoryBean.setAddress(address);  

  47.         factoryBean.create();  

  48.     }  

  49.   

  50.     @Test   

  51.     public void testList() {  

  52.         JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();  

  53.         factoryBean.setAddress(address);  

  54.         factoryBean.setServiceClass(UserService.class);  

  55.         Object obj = factoryBean.create();  

  56.           

  57.         Client client = ClientProxy.getClient(obj);  

  58.         Endpoint endpoint = client.getEndpoint();  

  59.           

  60.         Map<String,Object> props = new HashMap<String,Object>();  

  61.         props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);  

  62.         props.put(WSHandlerConstants.USER, "admin");  

  63.         props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);  

  64.         props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientUsernamePasswordHandler.class.getName());  

  65.         WSS4JOutInterceptor wss4JOutInterceptor = new WSS4JOutInterceptor(props);  

  66.         endpoint.getOutInterceptors().add(wss4JOutInterceptor);  

  67.           

  68.         HTTPConduit conduit = (HTTPConduit) client.getConduit();  

  69.         HTTPClientPolicy policy = new HTTPClientPolicy();  

  70.         policy.setConnectionTimeout(5 * 1000);  

  71.         policy.setReceiveTimeout(5 * 1000);  

  72.         conduit.setClient(policy);  

  73.           

  74.         UserService service = (UserService) obj;  

  75.         try {  

  76.             List<User> users = service.list();  

  77.             Assert.assertNotNull(users);  

  78.             Assert.assertEquals(10, users.size());  

  79.         } catch(Exception e) {  

  80.             if (e instanceof WebServiceException   

  81.                     && e.getCause() instanceof SocketTimeoutException) {  

  82.                 System.err.println("This is timeout exception.");  

  83.             } else {  

  84.                 e.printStackTrace();  

  85.             }  

  86.         }  

  87.     }  

  88.   

  89. }  

最后运行上面的测试类来测试结果,也可以修改测试方法中的密码,看看错误结果,这里就不在写错误密码的测试用例了,因为我是一懒人。

转载于:https://my.oschina.net/OkSerIous/blog/495694

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值