.net C# 调用 XFire发布的Webservice 安全访问控制

最近接触到的项目要使用.net调用xfire发布webservice,本文将阐述如何使用SOAP Header传递认证信息并且保存客户端的调用状态


这是.net 生成代理类的使用wsdl.exe工具 配置文档如下

view plain print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <wsdlParameters xmlns="http://microsoft.com/webReference/">  
  3.   <nologo>true</nologo>  
  4.   <parsableerrors>true</parsableerrors>  
  5.   <sharetypes>true</sharetypes>  
  6.   <namespace>ConsoleApplication1</namespace>  
  7.   <documents>  
  8.     <document>http://localhost:8080/v2/services/KillService?wsdl</document>  
  9.   </documents>  
  10. </wsdlParameters>  

服务器上我们添加验证方法

view plain print ?
  1. package com;  
  2. /** 
  3.  * @author Zhang Qi 
  4.  * @CreateTime 2009-12-30 
  5.  * **/  
  6. import java.util.Date;  
  7. import java.util.HashMap;  
  8. import java.util.Iterator;  
  9.   
  10. import org.codehaus.xfire.MessageContext;  
  11. import org.codehaus.xfire.fault.XFireFault;  
  12. import org.codehaus.xfire.handler.AbstractHandler;  
  13. import org.codehaus.xfire.transport.http.XFireServletController;  
  14.   
  15. import org.jdom.Element;  
  16. import org.jdom.Namespace;  
  17.   
  18. public class AuthenticationHandler extends AbstractHandler implements Runnable {  
  19.   
  20.     public AuthenticationHandler() {  
  21.   
  22.         // 该线程检查用户登录是否超时  
  23.         new Thread(this).start();  
  24.     }  
  25.   
  26.     // 定义hashMap 存储用户验证信息,key经过验证的用户IP,或者客户端特定信息  
  27.     HashMap<String, String> hash = new HashMap<String, String>();  
  28.   
  29.     // 当某个客户端登录成功后,纪录登录的时间,key 为经过验证的用户IP,或者客户端的特定信息  
  30.     HashMap<String, Date> createHashDate = new HashMap<String, Date>();  
  31.   
  32.     private final static Namespace TOKEN_NS = Namespace  
  33.             .getNamespace("demoService");  
  34.   
  35.     // 统计当前服务访问的人数  
  36.     Integer count = 0;  
  37.   
  38.     public void invoke(MessageContext context) throws Exception {  
  39.   
  40.         // 假如hash中存在用户验证信息,则直接跳出该函数,不再进行验证  
  41.         if (hash.containsKey(XFireServletController.getRequest()  
  42.                 .getRemoteAddr())) {  
  43.             return;  
  44.         }  
  45.   
  46.         // 得到客户soap header 对象  
  47.         Element header = context.getInMessage().getHeader();  
  48.         if (header == null) {  
  49.   
  50.             throw new XFireFault(  
  51.                     "Request must include company authentication token1.",  
  52.                     XFireFault.SENDER);  
  53.         }  
  54.   
  55.         // 得到认证令牌  
  56.         Element token = header.getChild("AuthenticationToken", TOKEN_NS);  
  57.   
  58.         if (token == null) {  
  59.             throw new XFireFault("Request must include authentication token.",  
  60.                     XFireFault.SENDER);  
  61.         }  
  62.   
  63.         Element name = token.getChild("name", TOKEN_NS);  
  64.         Element password = token.getChild("password", TOKEN_NS);  
  65.         if (name == null || password == null) {  
  66.             throw new XFireFault("AuthenticationToken Error,name or password is null", XFireFault.SENDER);  
  67.         }  
  68.         String nameValue = name.getValue();  
  69.         String passwordValue = password.getValue();  
  70.   
  71.         if (nameValue == null||passwordValue==null) {  
  72.             throw new XFireFault("name or password's value is null.", XFireFault.SENDER);  
  73.         }  
  74.         try {  
  75.             //进行服务器端验证  
  76.             if (nameValue.equals("admin") && passwordValue.equals("admin")) {  
  77.                 System.out.println("登录成功!登录时间:" + new Date());  
  78.                 System.out.println("当前人数:" + (++count));  
  79.                 hash.put(XFireServletController.getRequest().getRemoteAddr(),  
  80.                         XFireServletController.getRequest().getRemoteAddr());  
  81.                 createHashDate.put(XFireServletController.getRequest()  
  82.                         .getRemoteAddr(), new Date());  
  83.             } else {  
  84.                 System.out.println("fail login");  
  85.                 throw new Exception("Login fail");  
  86.             }  
  87.   
  88.         } catch (Exception e) {  
  89.             throw new XFireFault("Authentication Failed.", XFireFault.SENDER);  
  90.         }  
  91.     }  
  92.   
  93.     public void run() {  
  94.           
  95.         service();  
  96.     }  
  97.   
  98.     public synchronized void service() {  
  99.         while (true) {  
  100.             try {  
  101.                 /** 
  102.                  * 取出用户登录时间与当前时间进行对比 
  103.                  * 如果当前时间与用户登录时间之差大于系统设置的某个时间,则将用户登录信息清除 
  104.                  * **/  
  105.                 for (Iterator<String> keys = hash.keySet().iterator(); keys.hasNext();) {  
  106.                     Date now = new Date();  
  107.                     String key = keys.next();  
  108.                     long time = now.getTime()  
  109.                             - createHashDate.get(key).getTime();  
  110.                     if (time > 20*30 * 1000) {  
  111.                         System.out.println(now);  
  112.                         System.out.println(createHashDate.get(key));  
  113.                         synchronized (hash) {  
  114.                             hash.remove(key);  
  115.                         }  
  116.                         synchronized (count) {  
  117.                             count--;  
  118.                         }  
  119.                           
  120.                     }  
  121.                 }  
  122.                 //每10秒钟进行一次用户登录信息检测  
  123.                 Thread.sleep(10000);  
  124.             } catch (InterruptedException e) {  
  125.                   
  126.                 e.printStackTrace();  
  127.             }  
  128.         }  
  129.     }  
  130.   
  131. }  

稍微解释下此段代码
当web服务器启动的时候,比如tomcat启动的时候,该类将被实列化,生命周期直到tomcat关闭的时候结束

 

服务器services.xml

配置如下

view plain print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://xfire.codehaus.org/config/1.0">  
  3.   
  4.     <service xmlns="http://xfire.codehaus.org/config/1.0">  
  5.   
  6.         <name>demoService</name>  
  7.         <namespace>demoService</namespace>  
  8.         <serviceClass>com.kiloway.webservice.demo.Iservice</serviceClass>  
  9.         <implementationClass>com.kiloway.webservice.demo.serviceImpl</implementationClass>  
  10.         <inHandlers>  
  11.             <handler handlerClass="com.kiloway.webservice.demo.AuthenticationHandler"></handler>  
  12.         </inHandlers>  
  13.         <mce:style><!-- 
  14. wrapped 
  15. --></mce:style><style mce_bogus="1">wrapped</style>  
  16.         <use>literal</use>  
  17.         <scope>application</scope>  
  18.     </service>  
  19. </beans>  


.net客户端调用的时候添加一个类

view plain print ?
  1. 客户端采用.net调用  
  2. 添加客户端的AuthenticationToken  
  3. 具体代码如下  
  4. using System;  
  5. using System.Collections.Generic;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Web.Services;  
  9. using System.Web.Services.Protocols;  
  10.   
  11. namespace ConsoleApplication1  
  12. {  
  13.     [System.Serializable]  
  14.     [System.Xml.Serialization.XmlType(Namespace = "demoService")]  
  15.     [System.Xml.Serialization.XmlRoot(Namespace = "demoService", IsNullable = false)]  
  16.     public class AuthenticationToken : SoapHeader  
  17.     {  
  18.         public string name = null;  
  19.         public string password = null;  
  20.     }    
  21.   
  22. }  

然后再生成的代理类里面添加

view plain print ?
  1. public AuthenticationToken SoapHeader = new AuthenticationToken();    

在生成的代理类的调用方法上再添加如下代码

view plain print ?
  1. [SoapHeader("SoapHeader")]   

 

在调用该方法时候,验证信息将被加入soap header

 

调用采用

view plain print ?
  1. demoService demo = new demoService();  
  2.             while (true)  
  3.             {  
  4.                 demo.SoapHeader.name = "admin";  
  5.                 demo.SoapHeader.password = "admin";  
  6.                 System.Console.WriteLine(demo.sum(1, 23));  
  7.                 System.Console.WriteLine(demo.example("Hello,Kity"));  
  8.             }  

 

你可能感兴趣的:(.net C# 调用 XFire发布的Webservice 安全访问控制)