• WCF安全:通过 扩展实现用户名密码认证


      在webSservice时代,可以通过SOAPHEADER的方式很容易将用户名、密码附加到SOAP header消息头上,用户客户端对调用客户端身份的验证。在WCF 时代,也可以通过OperationContext.Current.IncomingMessageHeaders的方式将用户名、密码附加到SOAP消息中。但是这种方式实现起来有个缺点;那就是所有调用客户端都需要这样做才能将我们需要通过认证的帐号、密码附加到SOAP消息上。实际上,也可以通过WCF扩展的方式,在客户端自动将用户名、密码附加到SOAP消息中。这即是本文主题。

    1、客户端消息自动附加用户名、密码
      实现IClientMessageInspector接口,用于附加调用者的账号、密码信息

     public class ClientMessageInspector : IClientMessageInspector
        {
            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
                
            }
    
            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
                MessageHeader userNameHeader = MessageHeader.CreateHeader("OperationUserName", "http://tempuri.org", "account", false, "");
                MessageHeader pwdNameHeader = MessageHeader.CreateHeader("OperationPwd", "http://tempuri.org", "password", false, "");
                request.Headers.Add(userNameHeader);
                request.Headers.Add(pwdNameHeader);
                Console.WriteLine(request);
                return null;
            }
        }

    2、实现IEndpointBehavior 接口。用户将客户端的消息检查器添加到clientruntime的消息检查器集合中.注意,以下代码中为了简单将服务端分发消息检查器也添加到服务端终结点分发器(EndpointDispatcher)的分发运行时的消息检查器中。

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                clientRuntime.MessageInspectors.Add(new ClientMessageInspector());//客户端使用
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageDispatcher());//服务端使用
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
                
            }

    3、实现抽象类BehaviorextensionElement.用于在配置文件中配置对WCF服务行为的扩展

     internal class MessageBindingElement : BehaviorExtensionElement
        {
            public override Type BehaviorType
            {
                get { return typeof (MessageEndpointBehavior); }
            }
    
            protected override object CreateBehavior()
            {
                return new MessageEndpointBehavior();
            }
        }

    4、服务端验证客户端的账号、密码

    实现IDispatcherMessageInspector

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                Console.WriteLine(request);
                string userName = GetHeaderValue("OperationUserName");
                string pwd = GetHeaderValue("OperationPwd");
                if ("account" == userName && "password" == pwd)
                {
                    return null;
                }
                throw new Exception("用户名、密码错误");
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                
            }
    
            string GetHeaderValue(string key)
            {
                int index = OperationContext.Current.IncomingMessageHeaders.FindHeader(key, "http://tempuri.org");
                if (index >= 0)
                {
                    return OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index).ToString();
                }
                return null;
            }

    5、服务端配置;

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <extensions>
          <behaviorExtensions>
            <add name="messageInterptor" type="MessageInterceptor.MessageBindingElement,MessageInterceptor"/>
          </behaviorExtensions>
        </extensions>
        <behaviors>
          <endpointBehaviors>
            <behavior name="messageBehavior">
              <messageInterptor />
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <services>      
          <service name="Services.CalculatorService">
            <endpoint address="net.tcp://127.0.0.1:8081/CalculateService" 
                      binding="netTcpBinding" 
                      contract="Contracts.ICalculator" 
                      behaviorConfiguration="messageBehavior"></endpoint>
          </service>
        </services>
      </system.serviceModel>
    </configuration>

    6、客户端配置;

    <?xml version="1.0"?>
    <configuration>
      <system.serviceModel>
        <client>
          <endpoint name="calculatorService"
                    address="net.tcp://127.0.0.1:8081/CalculateService"
                    binding="netTcpBinding"
                    contract="Contracts.ICalculator" 
                    behaviorConfiguration="messageBehavior">
          </endpoint>
        </client>
        <extensions>
          <behaviorExtensions>
            <add name="messageInterptor" type="MessageInterceptor.MessageBindingElement,MessageInterceptor"/>
          </behaviorExtensions>
        </extensions>
        <behaviors>
          <endpointBehaviors>
            <behavior name="messageBehavior">
              <messageInterptor />
            </behavior>
          </endpointBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    7、运行结果图;

    服务端;

    客户端;

  • 相关阅读:
    一些大佬博客里的个签
    后缀子串排序
    PAT 1024 Palindromic Number[难]
    dp训练
    字符串最长子串匹配dp矩阵[转载]
    最短路径并查集+Floyd[转载]
    素数牛客网[求大数内所有素数]
    sql server 的规格参数,限制等 (zz)
    sql server varchar(max), NVARCHAR(MAX), VARBINARY(MAX) (zz)
    Oracle Data Types NVARCHAR2 (zz)
  • 原文地址:https://www.cnblogs.com/tyb1222/p/3493879.html
Copyright © 2020-2023  润新知