<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WCF進(jìn)階:為每個(gè)操作附加身份信息

         上文WCF進(jìn)階:將消息正文Base64編碼中介紹了實(shí)現(xiàn)自定義MessageInspector來記錄消息和實(shí)現(xiàn)自定義Formatter來改寫消息,本文介紹一下在WCF中使用SoapHeader進(jìn)行驗(yàn)證的兩種實(shí)現(xiàn)方法,同時(shí)再次復(fù)習(xí)自定義Inspector和自定義EndpointBehavior。

      在Xml Web Service中能將用戶的身份信息如用戶名,密碼添加到SoapHeader中,從而實(shí)現(xiàn)服務(wù)調(diào)用的身份驗(yàn)證,這種做法是沿用了Http中用戶名,密碼身份驗(yàn)證,是我們最樂于接受的。而在WCF中因?yàn)樘峁┝朔浅=训陌踩珯C(jī)制,但實(shí)現(xiàn)起來真是不夠簡單。對于多數(shù)應(yīng)用情景來講,有點(diǎn)大炮打蚊子的感覺。因此好多人在網(wǎng)上詢問在WCF中如何象XMl Web Service一樣使用SoapHeader來完成用戶名,密碼身份驗(yàn)證。傳統(tǒng)的辦法是通過在服務(wù)的操作中從OperationContext.Current.IncomingMessageHeaders來獲取Header中的內(nèi)容,而在客戶端在OperationContext.Current.OutgoingMessageHeaders中添加MessageHeader。下面的代碼片段簡要的介紹了這種實(shí)現(xiàn):

      在服務(wù)端的一個(gè)Operation中

      public string GetData(int value)

      {

      System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("utf-8");

      string username = "";

      string pwd = "";

      int index = OperationContext.Current.IncomingMessageHeaders.FindHeader("username", "http://tempuri.org");

      if (index >= 0)

      {

      username = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index).ToString();

      }

      index = OperationContext.Current.IncomingMessageHeaders.FindHeader("pwd", "http://tempuri.org");

      if (index >= 0)

      {

      pwd = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index).ToString();

      }

      return string.Format("You entered: {0}", value);

      }

      在客戶端調(diào)代碼如下:

      Robin_Wcf_Formatter_Svc.Service1Client svc = new Robin_Wcf_Formatter_Svc.Service1Client();

      using (OperationContextScope scope = new OperationContextScope(svc.InnerChannel))

      {

      MessageHeader header = MessageHeader.CreateHeader("username", "http://tempuri.org", "robinzhang");

      OperationContext.Current.OutgoingMessageHeaders.Add(header);

      header = MessageHeader.CreateHeader("pwd", "http://tempuri.org", "robinzhang");

      OperationContext.Current.OutgoingMessageHeaders.Add(header);

      string res = svc.GetData(10);

      }

       

      通過上邊的代碼實(shí)現(xiàn),已經(jīng)能在WCF中使用SoapHeader來傳遞身份信息了。但這種方式需要在每次客戶端調(diào)用和每個(gè)服務(wù)操作中都增加類似代碼片斷。比較麻煩。多數(shù)情況下,我們的服務(wù)開發(fā)好之后,往往只開放給固定的用戶用于消費(fèi),如果我們的服務(wù)的實(shí)例模式為PerCall,也就是不保存會話,同時(shí)我們又希望能驗(yàn)證調(diào)用者的身份信息,我們需要在每個(gè)Operation的消息中增加SoapHeader來附加身份信息。這樣服務(wù)即可保證每一個(gè)操作都不被非法調(diào)用。閱讀完上篇文章,已經(jīng)了解到通過MessageInspector能攔截消息用于記錄或者修改,如果在攔截到消息之后,在消息中增加MessageHeader便可以實(shí)現(xiàn)上述需求。為此我們實(shí)現(xiàn)了一個(gè)實(shí)現(xiàn)IClientMessageInspector, IDispatchMessageInspector, IEndpointBehavior三個(gè)接口的類,這樣該類就承擔(dān)了兩種角色,自定義MessageInspector,自定義EndpointBehavior。這個(gè)類的代碼如下:

       

      using System;

      using System.Collections.Generic;

      using System.Linq;

      using System.Text;

      using System.ServiceModel.Dispatcher;

      using System.ServiceModel.Description;

      using System.ServiceModel.Channels;

      using System.ServiceModel;

       

      namespace RobinLib

      {

      public class AttachUserNamePasswordBehavior : IClientMessageInspector, IDispatchMessageInspector, IEndpointBehavior

      {

      private static string UserName = System.Configuration.ConfigurationSettings.AppSettings["username"];

      private static string Password = System.Configuration.ConfigurationSettings.AppSettings["pwd"];

       

      public AttachUserNamePasswordBehavior()

      {

      }

       

       

      #region IClientMessageInspector 成員

       

      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 userNameHeader = MessageHeader.CreateHeader("OperationUserName", "http://tempuri.org", UserName, false, "");

      MessageHeader pwdNameHeader = MessageHeader.CreateHeader("OperationPwd", "http://tempuri.org", Password, false, "");

      request.Headers.Add(userNameHeader);

      request.Headers.Add(pwdNameHeader);

      Console.WriteLine(request);

      return null;

      }

       

      #endregion

       

      #region IDispatchMessageInspector 成員

       

      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;

      }

       

      public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)

      {

      Console.WriteLine(request);

      string username = GetHeaderValue("OperationUserName");

      string pwd = GetHeaderValue("OperationPwd");

      if (username == "robinzhang" && pwd == "111111")

      {

      }

      else

      {

      throw new Exception("操作中的用戶名,密碼不正確!");

      }

      return null;

      }

       

      public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

      {

       

      }

       

      #endregion

       

      #region IEndpointBehavior 成員

       

      public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

      {

       

      }

       

      public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

      {

      clientRuntime.MessageInspectors.Add(new AttachUserNamePasswordBehavior());

      }

       

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

      {

      endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new AttachUserNamePasswordBehavior());

      }

       

      public void Validate(ServiceEndpoint endpoint)

      {

       

      }

       

      #endregion

      }

      }

       

      象上文一樣,將自定義的EndpointBehavior通過代碼方式應(yīng)用到Host和Proxy中

       

      服務(wù)宿主程序

      using System;

      using System.Collections.Generic;

      using System.Linq;

      using System.Text;

      using System.ServiceModel;

       

      namespace Robin_Wcf_OperationWithToken_Host

      {

      public class Program

      {

      static void Main(string[] args)

      {

      //服務(wù)地址

      Uri baseAddress = new Uri("net.tcp://127.0.0.1:8081/Robin_Wcf_Formatter");

      ServiceHost host = new ServiceHost(typeof(Robin_Wcf_OperationWithToken_SvcLib.Service1), new Uri[] { baseAddress });

      //服務(wù)綁定

      NetTcpBinding bind = new NetTcpBinding();

      host.AddServiceEndpoint(typeof(Robin_Wcf_OperationWithToken_SvcLib.IService1), bind, "");

      if (host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>() == null)

      {

      System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();

      svcMetaBehavior.HttpGetEnabled = true;

      svcMetaBehavior.HttpGetUrl = new Uri("http://127.0.0.1:8001/Mex");

      host.Description.Behaviors.Add(svcMetaBehavior);

      }

      host.Opened += new EventHandler(delegate(object obj, EventArgs e)

      {

      Console.WriteLine("服務(wù)已經(jīng)啟動!");

      });

      foreach (var sep in host.Description.Endpoints)

      {

      sep.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

      host.Open();

      Console.Read();

      }

      }

      }

       

      客戶端代理

      [System.Diagnostics.DebuggerStepThroughAttribute()]

      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

      public partial class Service1Client : System.ServiceModel.ClientBase<Robin_Wcf_OperationWithToken_ClientApp.ServiceReference1.IService1>, Robin_Wcf_OperationWithToken_ClientApp.ServiceReference1.IService1

      {

       

      public Service1Client()

      {

      base.Endpoint.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

       

      public Service1Client(string endpointConfigurationName) :

      base(endpointConfigurationName)

      {

      base.Endpoint.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

       

      public Service1Client(string endpointConfigurationName, string remoteAddress) :

      base(endpointConfigurationName, remoteAddress)

      {

      base.Endpoint.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

       

      public Service1Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :

      base(endpointConfigurationName, remoteAddress)

      {

      base.Endpoint.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

       

      public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :

      base(binding, remoteAddress)

      {

      base.Endpoint.Behaviors.Add(new RobinLib.AttachUserNamePasswordBehavior());

      }

       

      public string GetData(int value)

      {

      return base.Channel.GetData(value);

      }

       

      public Robin_Wcf_OperationWithToken_ClientApp.ServiceReference1.CompositeType GetDataUsingDataContract(Robin_Wcf_OperationWithToken_ClientApp.ServiceReference1.CompositeType composite)

      {

      return base.Channel.GetDataUsingDataContract(composite);

      }

      到此,代碼基本實(shí)現(xiàn)了,在正式應(yīng)用的時(shí)候,我們只需要為每個(gè)客戶端創(chuàng)建獨(dú)立的用戶名,密碼對,然后將這個(gè)信息通過一些渠道告訴服務(wù)消費(fèi)者,服務(wù)消費(fèi)者需要將用戶名,密碼放到Web.Config中的AppSettings中。而且在正式應(yīng)用的時(shí)候,需要將放置到MessageHeader中的用戶名,密碼進(jìn)行加密,而不是明文傳輸。這樣這套機(jī)制就能用于生產(chǎn)啦。

       

      通過這種辦法,我們能為每個(gè)操作都設(shè)定身份驗(yàn)證,同時(shí)不需要更改Operation函數(shù)內(nèi)容和客戶端調(diào)用方式,我們來看一下運(yùn)行結(jié)果:

       

      用戶,密碼正確情況下的調(diào)用

      服務(wù)器端:

      客戶端:

       

      如果用戶名,密碼不匹配,服務(wù)能正常運(yùn)行,但客戶端會遇到異常

       

       

      示例程序:/Files/jillzhang/Robin_Wcf_CallOperationWithToken.rar

       

      posted @ 2010-04-11 11:06  Robin Zhang  閱讀(11323)  評論(12)    收藏  舉報(bào)
      主站蜘蛛池模板: 免费看的一级毛片| 日本一级午夜福利免费区 | 亚洲国内精品一区二区| 亚洲精品久荜中文字幕| 国产精品先锋资源站先锋影院| 亚洲欧洲一区二区精品| 日本亚洲欧洲免费无线码| 美乳丰满人妻无码视频| 野外做受三级视频| 黑人精品一区二区三区不| 国产精品一区在线蜜臀| 漂亮的保姆hd完整版免费韩国| 小伙无套内射老熟女精品| 丁香婷婷综合激情五月色 | 国产精品国产精品国产专区| 自拍亚洲一区欧美另类| 伊伊人成亚洲综合人网7777| 亚洲性色AV一区二区三区| 亚洲国产精品综合久久2007| 毛片网站在线观看| 亚洲欧洲精品国产二码 | 国产精品美女免费无遮挡| 久久天天躁狠狠躁夜夜躁2012| 精品一区二区久久久久久久网站| 一区二区福利在线视频| 国产精品麻豆欧美日韩ww| 亚洲av永久无码精品网站| 免费国产午夜理论片不卡| 欧美牲交a欧美牲交aⅴ图片| 日本亚洲一区二区精品久久| 国产农村妇女aaaaa视频| 在线成人国产天堂精品av| 精品999日本久久久影院| 亚洲国产精品无码一区二区三区| 国产在线视频不卡一区二区| 国产成人欧美一区二区三区| 妺妺窝人体色www婷婷| 国产成人麻豆亚洲综合无码精品| 无遮高潮国产免费观看| 又湿又紧又大又爽A视频男| 久久精品无码av|