在与WCF服务交互过程中传递用户信息等附加信息

本文介绍了一种在WCF应用中实现类似Web应用中的Session管理的方法。通过扩展MessageHeader,客户端能够在每次请求服务时传递用户身份信息,服务端则进行相应的权限验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 Web应用中,我们可以使用SessionCookies在浏览器与Server间维护会话状态及传递附加信息。假设有这样的需求,用户正常登陆系统后,Server产生一个UserIdentity发送到Client端,在此后的Client每次调用Service时都需要传递此UserIdentity传递到Server端以进行用户身份认证及权限审核。在WCF应用中有没有什么方法可以实现同样功能呢?

首先我们看看MSDN中对WCFSession的说明:
它们由调用应用程序显式启动和终止。
会话期间传递的消息按照接收消息的顺序进行处理。
会话将一组消息相互关联,从而形成对话。该关联的含义是抽象的。例如,一个基于会话的通道可能会根据共享网络连接来关联消息,而另一个基于会话的通道可能会根据消息正文中的共享标记来关联消息。可以从会话派生的功能取决于关联的性质。
不存在与 WCF 会话相关联的常规数据存储区。
最后一句告诉我们,WCF中的Session是无法像Web应用一样存储附加信息的。
经过研究,我们可以通过扩展MessageHeader实现一个附加的数据存储区在Client端每次请求Service时发送到Server端。具体实现如下(以前述需求为例)。
首先我们定义一个类作为交互过程中的UserIdentity,代码如下:
using System;
using System.Collections.Generic;
using System.Text;

namespace BNCommonPlus.BNCommonModel
{
    [Serializable]
    
public class UserIdentity
    
{
        
public string UserName = string.Empty;
        
public string UserRuningSystemID = string.Empty;
        
public string UserSysGUID = string.Empty;                
    }

}


这里使用[Serializable]作为序列化方式。在这个类中,UserName对应用户名,UserRuningSystemID对应用户已登陆的系统IDUserSysGUID对应用户当前的有效登陆。用户登录后Server产生这个类的一个实例回传ClientClient将其保存在缓存里,这里我定义了一个类来作为缓存,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using BNCommonPlus.BNCommonModel;
namespace BNIIClientLayerPlus
{
    
public class UserPermissionInfo
    
{
        
private UserPermissionInfo()
        
{ }
        
private static UserPermissionInfo _Instance = null;
        
public static UserPermissionInfo GetInstance()
        
{
            
if (_Instance == null)
            
{
                _Instance 
= new UserPermissionInfo();
            }

            
return _Instance;
        }

        
private UserIdentity _userIdentity = null;
        
public UserIdentity _UserIdentity
        
{
            
get
            
{
                
return _userIdentity;
            }

        }


        
public void SetUserIdentity(UserIdentity ui)
        
{
            _userIdentity 
= ui;
        }

    }

}


 
这是一个单件类,Client正常登陆得到Server端回传的UserIdentity实例后可以通过如下代码将其存入缓存:
UserPermissionInfo.GetInstance().SetUserIdentity(ServerReturnedUserIdentity);
其中ServerReturnedUserIdentity就是Server产生并回传的UserIdentity 
下面我们扩展MessageHeader将我们自己定义的UserIdentity加入进去,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceProcess;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
namespace BNCommon.ClientHelper
{
public class BNClientMessageInspector : IClientMessageInspector
    
{
        
IClientMessageInspector 成员
   }

}


 
这个类实现了IClientMessageInspector接口,实现该接口可以在Client每次向Server请求前及请求返回后控制Client的行为对发送和接收的数据进行处理。
现在我们需要实现BehaviorExtensionElement, IEndpointBehavior将刚刚建立的行为加入Client行为集合,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceProcess;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;

namespace BNCommon.ClientHelper
{
    
public class BNClientEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
    
{
        
IEndpointBehavior 成员
        
public override Type BehaviorType
        
{
            
get return typeof(BNClientEndpointBehavior); }
        }

        
protected override object CreateBehavior()
        
{
            
return new BNClientEndpointBehavior();
        }

    }

}


 
现在我们定义了Client在用户正常登陆后,每次请求都会发送缓存里面的UserIdentity实例。然后需要修改Client端的代理类,这里要分两种情况:如果客户端使用的是”SvcUtil.exe”工具生成的代理类,则需要修改对应Client的构造方法,加入如下代码:
Endpoint.Behaviors.Add(new BNCommonPlus.ClientHelper.BNClientEndpointBehavior());
如果使用ChanelFactory则需要在Create对应得ChanelFactory后加入如下代码:
_ChannelFactory.Endpoint.Behaviors.Add(new BNClientEndpointBehavior());
当然也可以通过配置文件实现上述目的。
搞定Client端后,再来看看Server端如何取Client每次发送过来的附加信息.
首先在Server端要实现IDispatchMessageInspector接口,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using BNCommonPlus.BNCommonModel;
namespace BNCommonPlus.ServiceHelper
{
    
public class DispatchMessageInspector : IDispatchMessageInspector
    
{
        
IDispatchMessageInspector 成员
    }

}

 
和客户端一样将上面定义的行为加入行为集合,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using BNCommonPlus.BNCommonModel;
namespace BNCommonPlus.ServiceHelper
{    
   
public class BNServiceOperationBehavior : BehaviorExtensionElement, IEndpointBehavior
   
{
       
IEndpointBehavior 成员        
   }

}


 
最后将扩展出来的行为加入到ServiceHost上:
for (int j = 0; j < _ServiceHost.Description.Endpoints.Count; j++)
{
      _ServiceHost.Description.Endpoints[j].Behaviors.Add(new BNServiceOperationBehavior());
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值