使用.net调用xfire发布webservice的统一安全认证

使用.net调用xfire发布webservice的统一安全认证

 

        在实际的项目中,服务端采用java框架,客户端采用C#.net框架,客户端通过访问Xfirejava WebSevcie服务来实现与客户端的非实时数据交换;

       如何对客户端访问的WebService进行授权认证,是必须要考虑的问题,对客户端个访问的每个服务都认证太繁琐,是否可以采用对业务无侵入的外挂式认证呢?是我们必须要考虑的问题?

       本文采用对登录方法进行SoapHeader认证,并在服务端记录客户端的认证的状态(服务端的安全处理Handler是有状态的),在认证有效的时间内,认证过的客户端访问其他服务,无需再进行认证。

该方案虽然存在一定的严密性缺陷(小权限访问多接口),但是在实际的应用中,却不失为一个性价比很好的解决方案;

 

1.     使用wsdl.exe工具生成.net访问Xfire服务的代理类,指令如下:

Doc控制台执行如下指令:

wsdl /language:c# /sharetypes /n:vvdcmonitor.vvdcm.module /out:C:\Users\Administrator\Desktop\vvmc_test.cs http://192.168.1.126:88//service/Test?wsdl

 

 

2.     服务器上添加自定义的验证方法

web服务器启动的时候,比如tomcat启动的时候,该类将被实列化,生命周期直到tomcat关闭的时候结束

代码如下:

package org.ServiceAuthentication;

 

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

 

import org.codehaus.xfire.MessageContext; 

import org.codehaus.xfire.fault.XFireFault;

import org.codehaus.xfire.handler.AbstractHandler; 

import org.codehaus.xfire.transport.http.XFireServletController;

import org.jdom.Element; 

import org.jdom.Namespace; 

/**

 * 认证拦截和缓存

 *  

 * @authorzhx

 *

 */

publicclassAuthenticationHandler extends AbstractHandler implements Runnable 

 

    //定义hashMap 存储用户验证信息,key经过验证的用户IP,或者客户端特定信息  

    private HashMap<String, ClientAuthenticationInfo> clientAuthenticationInfoMap =new HashMap<String, ClientAuthenticationInfo>();

    privatefinalstatic NamespaceTOKEN_NS = Namespace.getNamespace("http://tempuri.org/"); 

 

    public AuthenticationHandler() { 

        //该线程检查用户登录是否超时  

        new Thread(this).start(); 

   

   

    /**

     * 认证拦截

     * 仅登录方法增加认证,所有必须登录方法调用成功后,其他方法才可以调用

     */

    publicvoid invoke(MessageContext cfx)throws Exception { 

      

       //为简化变更时,对WebServcies代理桩的修改工作量,仅仅登录函数增加 SoapHeader,其他函数并不增加

       //假如clientAuthenticationInfoMap中存在用户验证信息,则直接跳出该函数,不再进行验证  

        if (clientAuthenticationInfoMap.containsKey(XFireServletController.getRequest().getRemoteAddr())){

            return

       

 

       //得到客户soap header对象  

       Element header=cfx.getInMessage().getHeader();

       if ( header==null) {//为简化变更时,对WebServcies代理桩的修改工作量,仅仅登录函数增加 SoapHeader,其他函数并不增加; 

          thrownew org.codehaus.xfire.fault.XFireFault("您超过1小时没有进行任何操作,您的认证信息已经失效,需要对您进行重新身份认证,请重新登录!",org.codehaus.xfire.fault.XFireFault.SENDER);

       } 

     

       // 得到认证令牌  

       Element token = header.getChild("AuthenticationToken",TOKEN_NS); 

       if (token ==null) { 

        thrownew org.codehaus.xfire.fault.XFireFault("对服务的访问,必须包含认证信息!",org.codehaus.xfire.fault.XFireFault.SENDER); 

       } 

     

       Element Username = token.getChild("Username",TOKEN_NS); 

       Element password = token.getChild("Password",TOKEN_NS); 

       if (Username ==null || password ==null) { 

           thrownew XFireFault("AuthenticationToken Error,name or password is null", XFireFault.SENDER); 

       } 

       String nameValue = Username.getValue(); 

       String passwordValue = password.getValue(); 

   

       if (nameValue ==null||passwordValue==null) { 

           thrownew XFireFault("name or password's value is null.", XFireFault.SENDER); 

       } 

   

       try

           // 进行身份验证 ,只有abcd@1234的用户为授权用户  

           if (checkLogin(nameValue,passwordValue)){// 

               // 这语句不显示  

               System.out.println("身份验证通过");

              

               //通过身份认证记录用户认证信息

               ClientAuthenticationInfo clientLoginInfo=new ClientAuthenticationInfo();

               clientLoginInfo.setClientIpAddr(XFireServletController.getRequest().getRemoteAddr());

               clientLoginInfo.setLoginTime(new Date());

               clientLoginInfo.setLastRequestServerTime(new Date());

               clientAuthenticationInfoMap.put(clientLoginInfo.getClientIpAddr(),clientLoginInfo); 

              

           }

           else

              thrownew Exception();

           }

       

       } catch (Exception e) { 

            thrownew org.codehaus.xfire.fault.XFireFault("对访问服务时,提供的用户名或密码无效",org.codehaus.xfire.fault.XFireFault.SENDER); 

       }

      

     }

   

    /**

     * 检测用户登录认证

     * @param userName

     * @param password

     * @return

     */

    privateboolean checkLogin(String userName,String password){

       if (userName.equals("abcd") && password.equals("1234")){

          returntrue;

       }

       returnfalse;

    }

   

    /**

     * 客户端登录信息

     * @authorzhx

     *

     */

     privateclass ClientAuthenticationInfo{

        //登录客户端的IP

        private StringclientIpAddr="";

        public String getClientIpAddr() {

           returnclientIpAddr;

       }

       publicvoid setClientIpAddr(String clientIpAddr) {

           this.clientIpAddr = clientIpAddr;

       }

       //客户端登录时间

       private DateloginTime=new Date();

       public DategetLoginTime() {

           returnloginTime;

       }

       publicvoid setLoginTime(Date loginTime) {

           this.loginTime = loginTime;

       }

        //客户端最后访问时间

       private DatelastRequestServerTime=new Date();

       public Date getLastRequestServerTime() {

           returnlastRequestServerTime;

       }

       publicvoid setLastRequestServerTime(Date lastRequestServerTime) {

           this.lastRequestServerTime = lastRequestServerTime;

       }

      

       /**

        * 检测用户认证信息是否超时

        * @return

        */

       publicboolean checkLoginInfo(){

            Date now = new Date(); 

            long time = now.getTime()-this.getLastRequestServerTime().getTime();

            if (time >authenticationTimeOut) { 

               

               returnfalse;

            }

            returntrue;

        }

     }

     

     /**

      * 启动线程定时检测

      */

     publicvoid run() {     

            checkClientAuthenticationInfo(); 

     } 

     

     /**

      * 认证超时时间

      */

     privatelongauthenticationTimeOut=1000*60*60;//最后一次请求后1小时,认证失效;

     

     /**

      * 检测客户端认证信息是否失效

      * 认证通过的客户端IP,最后访问中心服务时间,超过设定的阀值时,认证信息将失效,必须重新登录并认证

      */

      publicsynchronizedvoid checkClientAuthenticationInfo() { 

            while (true) { 

                try

                    /**

                     *

                     * **/ 

                    for (Iterator<String> keys =clientAuthenticationInfoMap.keySet().iterator(); keys.hasNext();) { 

                      

                        String key = keys.next();

                        ClientAuthenticationInfo clientInfo=clientAuthenticationInfoMap.get(key);

                      

                        if (!clientInfo.checkLoginInfo()) { 

                         

                            synchronized (clientAuthenticationInfoMap) { 

                                clientAuthenticationInfoMap.remove(key); 

                            }

                        } 

                    } 

                    //每10秒钟进行一次用户登录信息检测  

                    Thread.sleep(10000); 

                } catch (InterruptedException ex) { 

                  

                   System.out.println(ex.getMessage());

                } 

            }

      }

}

3.     服务器services.xmlxFire的服务配置文件)

配置如下

<service xmlns="http://xfire.codehaus.org/config/1.0">

    <name>Test</name>

    <namespace>http://tempuri.org/</namespace>

    <serviceClass>webservice.ITest</serviceClass>

    <implementationClass>webservice.Test</implementationClass>

    <inHandlers>

      <handler handlerClass="org.ServiceAuthentication.AuthenticationHandler" ></handler>

   </inHandlers>

   <style>wrapped</style>

   <use>literal</use>

   <scope>application</scope>

</service>

 

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

客户端采用.net调用,添加客户端的AuthenticationToken

具体代码如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Web.Services;

using System.Web.Services.Protocols; 

 

namespace myWindowsFormsApp

{

    [System.Serializable]

    [System.Xml.Serialization.XmlType(Namespace ="http://tempuri.org/")]

    [System.Xml.Serialization.XmlRoot(Namespace ="http://tempuri.org/", IsNullable = false)]

    public class AuthenticationToken : SoapHeader

    {

        public string Username = null;

        public string Password = null;

    }   

 

}

5.     然后在生成的代理类里面添加以下代码

   public AuthenticationToken SoapHeader = new AuthenticationToken();

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

[SoapHeader("SoapHeader")]

 

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

 

7.     客户端调用实现

8.   using System;

9.   using System.Collections.Generic;

10.  using System.ComponentModel;

11.  using System.Data;

12.  using System.Drawing;

13.  using System.Linq;

14.  using System.Text;

15.  using System.Windows.Forms;

16.  using System.ServiceModel.Description;

17.  using vvdcmonitor.vvdcm.module;

18.   

19.  namespace myWindowsFormsApp

20.  {

21.      public partial class MyForm : Form

22.      {

23.          public MyForm()

24.          {

25.              InitializeComponent();

26.          }

27.   

28.          private void button1_Click(object sender, EventArgs e)

29.          {

30.              try

31.              {

32.                  Test client =new Test();

33.                  client.SoapHeader.Password = "1234";

34.                  client.SoapHeader.Username = "abcd";

35.                  MessageBox.Show("访问成功,返回:"+client.test(34).ToString());

36.              }catch(Exception ex){

37.                  MessageBox.Show("访问失败,原因:"+ex.Message);

38.              }

39.   

40.          }

41.      }

42.  }

43.   

 

44.   其他替代方法:

其实JavaC#通过Webservice通信的安全控制还是可以用session来控制的,只是客户端需要保存一cookieC#提供了一个cookieContainer类来为我们保存Session

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值