WCF中使用扩展行为来验证连接的用户

        在WCF实现安全控制的方法很多,如使用证书、windows身份认证等等。本文要介绍的是使用简单的用户名密码方式来验证,客户端在与服务端交互时附带传递用户名和密码。使用该方法的好处就是配置简单,不受环境的制约。

通过WCF中的扩展行为来将用户名和密码附加到消息头MessageHeader中,自然这样就可以在服务端通过读取IncomingMessageHeaders得到用户名和密码。

       自定义行为,自定义行为要实现:IEndpointBehavior BehaviorExtensionElement

IEndpointBehavior members:

ExpandedBlockStart.gif 代码
public   void  AddBindingParameters(ServiceEndpoint endpoint, 
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            
return ;
        }

        
public   void  ApplyClientBehavior(ServiceEndpoint endpoint, 
            System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(
new  IdentityHeaderInspector());
        }

        
public   void  ApplyDispatchBehavior(ServiceEndpoint endpoint, 
            System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {

        }

        
public   void  Validate(ServiceEndpoint endpoint)
        {
            
return ;
        }

 

BehaviorExtensionElement members

 

ExpandedBlockStart.gif 代码
   public   override  Type BehaviorType
        {
            
get
            {
                
return   typeof (AttachContextBehavior);
            }
        }

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

 


自定义消息检查器IClientMessageInspector,在消息检查器中添加MessageHeader附加用户名和密码:

ExpandedBlockStart.gif 代码
   private   class  IdentityHeaderInspector : IClientMessageInspector
        {
            
#region  IClientMessageInspector Members

            
public   void  AfterReceiveReply( ref  System.ServiceModel.Channels.Message reply,  object  correlationState)
            {
            }

            
public   object  BeforeSendRequest( ref  System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
                MessageHeader
< string >  header  =   new  MessageHeader < string > (AppContext.UserName);
                request.Headers.Add(header.GetUntypedHeader(
" UserName " " http://ruinet.cnblogs.com/username " ));

                header 
=   new  MessageHeader < string > (AppContext.Password);
                request.Headers.Add(header.GetUntypedHeader(
" Password " " http://ruinet.cnblogs.com/password " ));
                
return   null ;
            }

            
#endregion

        }

 

 

然后在实现的IEndpointBehavior接口的ApplyClientBehavior行为中添加IdentityHeaderInspector

ExpandedBlockStart.gif 代码
public   void  ApplyClientBehavior(ServiceEndpoint endpoint, 
            System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(
new  IdentityHeaderInspector());
        }

完整扩展行为代码:
ExpandedBlockStart.gif 代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.ServiceModel.Dispatcher;
using  System.ServiceModel;
using  System.ServiceModel.Description;
using  System.ServiceModel.Configuration;
using  WCFSecurity.Security;

namespace  WCFSecurity.Security
{
    
public   class  AttachContextBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
        
public   override  Type BehaviorType
        {
            
get
            {
                
return   typeof (AttachContextBehavior);
            }
        }

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

        
#region  IEndpointBehavior Members

        
public   void  AddBindingParameters(ServiceEndpoint endpoint, 
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            
return ;
        }

        
public   void  ApplyClientBehavior(ServiceEndpoint endpoint, 
            System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(
new  IdentityHeaderInspector());
        }

        
public   void  ApplyDispatchBehavior(ServiceEndpoint endpoint, 
            System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {

        }

        
public   void  Validate(ServiceEndpoint endpoint)
        {
            
return ;
        }

        
#endregion

        
private   class  IdentityHeaderInspector : IClientMessageInspector
        {
            
#region  IClientMessageInspector Members

            
public   void  AfterReceiveReply( ref  System.ServiceModel.Channels.Message reply,  object  correlationState)
            {
            }

            
public   object  BeforeSendRequest( ref  System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
                MessageHeader
< string >  header  =   new  MessageHeader < string > (AppContext.UserName);
                request.Headers.Add(header.GetUntypedHeader(
" UserName " " http://ruinet.cnblogs.com/username " ));

                header 
=   new  MessageHeader < string > (AppContext.Password);
                request.Headers.Add(header.GetUntypedHeader(
" Password " " http://ruinet.cnblogs.com/password " ));
                
return   null ;
            }

            
#endregion

        }
    }
}

 在客户端的配置文件中加入扩展行为AttachContextBehavior

 

ExpandedBlockStart.gif 代码
< behaviors >
            
< endpointBehaviors >
                
< behavior  name ="headersMapping" >
                    
< attachContextHeader />
                
</ behavior >
            
</ endpointBehaviors >
        
</ behaviors >
        
< extensions >
            
< behaviorExtensions >
                
< add  name ="attachContextHeader"  type ="WCFSecurity.Security.AttachContextBehavior, WCFSecurity.Security, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            
</ behaviorExtensions >
        
</ extensions >

 

behaviorExtensions节点中加入自定义对象,然后再behavior节点指定:<attachContextHeader/>,最后在endpoint的behaviorConfiguration指定行为即可:

 

ExpandedBlockStart.gif 代码
< endpoint name = " CalculateService "
    contract 
= " WCFSecurity.Contracts.ICalculateService "
    address
= " http://localhost:8001/CalculateService "
    binding 
= " wsHttpBinding "
    bindingConfiguration 
= " wsHttpBindingConfig "
    behaviorConfiguration 
= " headersMapping "   />

实例客户端运行时传递用名ruinet和密码88888:

 

ExpandedBlockStart.gif 代码
  static   void  Main( string [] args)
        {
            AppContext.UserName 
=   " ruinet " ;
            AppContext.Password 
=   " 888888 " ;

            Console.WriteLine(
" connecting host.. " );
            CalculateServiceProxy proxy 
=   new  CalculateServiceProxy();
            Console.WriteLine ( proxy.Add(
12 22 ));

            proxy.Close();

            Console.WriteLine(
" close connect " );
            Console.ReadLine(); 
        }

 

在服务器端接收用户名和密码:

 

ExpandedBlockStart.gif 代码
namespace  WCFSecurity.Services
{
    
public   class  CalculateService : WCFSecurity.Contracts.ICalculateService
    {
        
public   double  Add( double  num1,  double  num2)
        {
            Console.WriteLine(
" Client  Requirement is coming " );

            
int  index =  OperationContext.Current.IncomingMessageHeaders.FindHeader( " UserName "
                
" http://ruinet.cnblogs.com/username " );
            
if  (index  !=   - 1 )
            {
                
string  userName  =  OperationContext.Current.IncomingMessageHeaders.GetHeader < string > ( " UserName "
                    
" http://ruinet.cnblogs.com/username " );
                
string  password  =  OperationContext.Current.IncomingMessageHeaders.GetHeader < string > ( " Password "
                    
" http://ruinet.cnblogs.com/password " );

                Console.WriteLine(
" UserName: "   +  userName);
                Console.WriteLine(
" Password: "   +  password);
            }
          

            
return  num1  +  num2;
        }
    }
}

 

运行结果:

代码下载

转载于:https://www.cnblogs.com/ruinet/archive/2010/03/21/1690848.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值