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

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

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

      [WCF權限控制]通過擴展自行實現服務授權[提供源碼下載]

      其實針對安全主體的授權實現的原理很簡單,原則上講,只要你能在服務操作執行之前能夠根據本認證的用戶正確設置當前的安全主體就可以了。如果你了解WCF的整個運行時框架結構,你會馬上想到用于授權的安全主體初始化可以通過自定義CallContextInitializer來實現。[源代碼從這里下載]

      目錄:
      CallContextInitializer簡介
      步驟一、自定義CallContextInitializer
      步驟二、創建服務行為
      步驟三、使用服務行為進行授權

      CallContextInitializer簡介

      對于WCF的整個運行時框架來說,CallContextInitializer是一個重要的對象。一個運行時服務操作(DispatchOperation)具有一個CallContextInitializer列表。而每一個CallContextInitializer實現ICallContextInitializer接口。如下面的代碼片斷所示,ICallContextInitializer具有兩個方法BeforeInvoke和AfterInvoke。它們分別在操作方法之前前后進行調用上下文的初始化和清理操作。那么我么就可以自定義CallContextInitializer,在BeforeInvoke中初始化當前的安全主體。

         1: public interface ICallContextInitializer
         2: {
         3:     void AfterInvoke(object correlationState);
         4:     object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message);
         5: }

      步驟一、自定義CallContextInitializer

      我們授權自定義一個抽象的CallContextInitializer,起名為AuthorizationCallContextInitializerBase。下面的代碼片斷給出了AuthorizationCallContextInitializerBase的整個定義。AuthorizationCallContextInitializerBase具有一個抽象的方法GetPrincipal用于根據當前的安全上下文信息創建安全主體。該方法會在BeforeInvoke方法被調用,返回值被設置成當前線程的安全主體。為了讓服務操作執行之后當前線程的上下文恢復到執行前的狀態,在BeforeInvoke方法中當前的安全主體被保存下來,并傳遞給AfterInvoke方法中恢復當前線程的原來的安全主體。

         1: public abstract class AuthorizationCallContextInitializerBase: ICallContextInitializer
         2: {
         3:     public void AfterInvoke(object correlationState)
         4:     {
         5:         IPrincipal principal = correlationState as IPrincipal;
         6:         if (null != principal)
         7:         {
         8:             Thread.CurrentPrincipal = principal;
         9:         }
        10:     }
        11:     public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        12:     {
        13:         var originalPrincipal = Thread.CurrentPrincipal;
        14:         Thread.CurrentPrincipal = this.GetPrincipal(ServiceSecurityContext.Current);
        15:         return originalPrincipal;
        16:     }
        17:     protected abstract IPrincipal GetPrincipal(ServiceSecurityContext serviceSecurityContext);
        18: }

      基于兩種安全主體權限模式,我們創建了兩個具體的CallContextInitializer。第一個為基于Windows用戶組的WindowsAuthorizationCallContextInitializer。WindowsAuthorizationCallContextInitializer定義如下,它繼承了AuthorizationCallContextInitializerBase,在實現的抽象方法GetPrincipal中根據當前ServiceSecurityContext的WindowsIdentity屬性創建WindowsPrincipal。

         1: public class WindowsAuthorizationCallContextInitializer:AuthorizationCallContextInitializerBase
         2: {
         3:     protected override IPrincipal GetPrincipal(ServiceSecurityContext serviceSecurityContext)
         4:     {
         5:         WindowsIdentity identity = serviceSecurityContext.WindowsIdentity;
         6:         if (null == identity)
         7:         {
         8:             identity =WindowsIdentity.GetAnonymous();
         9:         }
        10:         return new WindowsPrincipal(identity);
        11:     }
        12: }

      而基于ASP.NET Roles安全主體權限模式的安全主體初始化實現在如下所示的AspRoleAuthorizationCallContextInitializer類中。AspRoleAuthorizationCallContextInitializer具有一個RoleProvider屬性,表示用于獲取當前用戶角色列表的RoleProvider,該屬性在構造函數中被初始化。在實現的GetPrincipal抽象方法中,借助于RoleProvider獲取基于當前用戶的所有角色,并創建GenericPrincipal。

         1: public class AspRoleAuthorizationCallContextInitializer : AuthorizationCallContextInitializerBase
         2: {
         3:     public RoleProvider RoleProvider { get; private set; }
         4:     public AspRoleAuthorizationCallContextInitializer(RoleProvider roleProvider)
         5:     {
         6:         this.RoleProvider = roleProvider;
         7:     }
         8:     protected override IPrincipal GetPrincipal(ServiceSecurityContext serviceSecurityContext)
         9:     {
        10:         var userName = serviceSecurityContext.PrimaryIdentity.Name;
        11:         var identity = new GenericIdentity(userName);
        12:         var roles = this.RoleProvider.GetRolesForUser(userName);
        13:         return new GenericPrincipal(identity, roles);
        14:     }
        15: }

      步驟二、創建服務行為

      現在,用戶進行安全主體初始化的兩個具體的CallContextInitializer已經創建完成,現在需要做的工作就是將其應用到WCF的運行時框架體系之中。為此,我們創建了如下一個服務行為ServiceAuthorizationBehaviorAttribute。ServiceAuthorizationBehaviorAttribute是一個自定義特性,并實現了IServiceBehavior接口。它具有兩個兩個屬性:PrincipalPermissionMode和CallContextInitializer。前者在構造函數中指定,我們根據該參數決定具體創建的CallContextInitializer類型,是WindowsAuthorizationCallContextInitializer還是AspRoleAuthorizationCallContextInitializer。而構造函數中具有一個可選的參數roleProviderName表示采用的RoleProvider配置名稱。

         1: [AttributeUsage( AttributeTargets.Class)]
         2: public class ServiceAuthorizationBehaviorAttribute: Attribute, IServiceBehavior
         3: {
         4:     public PrincipalPermissionMode PrincipalPermissionMode { get; private set; }
         5:     public ICallContextInitializer CallContextInitializer { get; private set; }
         6:  
         7:     public ServiceAuthorizationBehaviorAttribute(PrincipalPermissionMode principalPermissionMode, string roleProviderName = "")
         8:     {
         9:         switch (principalPermissionMode)
        10:         {
        11:             case PrincipalPermissionMode.UseWindowsGroups:
        12:                 {
        13:                     this.CallContextInitializer = new WindowsAuthorizationCallContextInitializer();
        14:                     break;
        15:                 }
        16:             case PrincipalPermissionMode.UseAspNetRoles:
        17:                 {
        18:                     if (string.IsNullOrEmpty(roleProviderName))
        19:                     {
        20:                         this.CallContextInitializer = new AspRoleAuthorizationCallContextInitializer(Roles.Provider);
        21:                     }
        22:                     else
        23:                     {
        24:                         this.CallContextInitializer = new AspRoleAuthorizationCallContextInitializer(Roles.Providers[roleProviderName]);
        25:                     }
        26:                     break;
        27:                 }
        28:             case PrincipalPermissionMode.Custom:
        29:                 {
        30:                     throw new ArgumentException("只有UseWindowsGroups和UseAspNetRoles模式被支持!");
        31:                 }
        32:         }
        33:     }
        34:  
        35:     public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
        36:  
        37:     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        38:     {
        39:         if (null == this.CallContextInitializer)
        40:         {
        41:             return;
        42:         }
        43:  
        44:         foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
        45:         {
        46:             foreach (EndpointDispatcher endpoint in channelDispatcher.Endpoints)
        47:             {
        48:                 foreach (DispatchOperation operation in endpoint.DispatchRuntime.Operations)
        49:                 {
        50:                     operation.CallContextInitializers.Add(this.CallContextInitializer);
        51:                 }
        52:             }
        53:         }
        54:     }
        55:     public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
        56: }

      CallContextInitializer的注冊實現在ApplyDispatchBehavior方法中,邏輯很簡單:遍歷所有信道分發器(ChannelDispatcher),每個信道分發器的所有終結點分發器(EndpointDispatcher),以及每個終結點分發器對應的分發運行時(DispatchRuntime)的所有運行時操作(DispatchOperation)。最后將初始化的CallContextInitializer添加到操作的CallContextInitializer列表中。

      步驟三、使用服務行為進行授權

      由于上面定義的服務行為ServiceAuthorizationBehaviorAttribute是一個自定義特性,所以我們可以直接將其應用到服務類型上。我們直接采用《基于Windows用戶組的授權方式[下篇]》的例子。如下所示,在服務類型CalculatorService上應用了ServiceAuthorizationBehaviorAttribute特性,并采用了UseWindowsGroups安全主體權限模式。

         1: [ServiceAuthorizationBehavior(PrincipalPermissionMode.UseWindowsGroups)]
         2: public class CalculatorService : ICalculator
         3: {
         4:     [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
         5:     public double Add(double x, double y)
         6:     {
         7:         return x + y;
         8:     }
         9: }

      為了證明我們自定義的服務行為也能和ServiceAuthorizationBehavior一樣實現正確的授權,我們需要將ServiceAuthorizationBehavior的授權功能關閉。為此我們修正了服務端的配置,將ServiceAuthorizationBehavior的PrincipalPermissionMode設置為None。

         1: <?xml version="1.0"?>
         2: <configuration>
         3:   <system.serviceModel>
         4:     <services>
         5:       <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="disableAuthorization">
         6:         <endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" contract="Artech.WcfServices.Contracts.ICalculator"/>
         7:       </service>
         8:     </services>
         9:     <behaviors>
        10:       <serviceBehaviors>
        11:         <behavior  name="disableAuthorization">
        12:           <serviceAuthorization principalPermissionMode="None"/>
        13:         </behavior>
        14:       </serviceBehaviors>
        15:     </behaviors>
        16:   </system.serviceModel>
        17: </configuration>

      而客戶端的服務調用程序中,依然是分別以Foo和Bar(Foo具有管理員權限)的名義進行兩次服服務調用。由于兩個Windows帳號權限的不同,同樣只有第一個服務調用能夠成功,這反映在最終的執行結果中??蛻舳顺绦颍?/p>

         1: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");
         2: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
         3: credential.UserName = "Foo";
         4: credential.Password = "Password";
         5: ICalculator calculator = channelFactory.CreateChannel();
         6: Invoke(calculator);
         7:  
         8: channelFactory = new ChannelFactory<ICalculator>("calculatorService");
         9: credential = channelFactory.Credentials.Windows.ClientCredential;
        10: credential.UserName = "Bar";
        11: credential.Password = "Password";
        12: calculator = channelFactory.CreateChannel();
        13: Invoke(calculator);

      輸出結果:

         1: 服務調用成功...
         2: 服務調用失敗...
      posted @ 2011-07-05 19:01  Artech  閱讀(7448)  評論(20)    收藏  舉報
      主站蜘蛛池模板: 成人自拍小视频在线观看| 精品人妻中文字幕av| 好紧好滑好湿好爽免费视频| 亚洲欧美高清在线精品一区二区| 日韩丝袜欧美人妻制服| 华人在线亚洲欧美精品| 天天躁夜夜躁狠狠喷水| 亚洲VA久久久噜噜噜久久无码| 国产精品美女一区二区三| 国产在线不卡精品网站| 日韩在线视频一区二区三| 策勒县| 国产第一页浮力影院入口| 国产在线精品欧美日韩电影| 美女裸体18禁免费网站| 九九热视频免费在线播放| 国产精品va无码一区二区| 少妇性bbb搡bbb爽爽爽欧美| 安阳县| 在线视频中文字幕二区| 大尺度国产一区二区视频| 国产青榴视频在线观看| 国产成人无码av大片大片在线观看| 国产精品成人av电影不卡| 亚洲熟女乱色综合亚洲图片| 海伦市| 亚洲国产超清无码专区| 久久日韩在线观看视频| 一本无码人妻在中文字幕免费 | 国产亚洲一区二区三不卡| 中文文字幕文字幕亚洲色| 久爱www人成免费网站| 自拍亚洲综合在线精品| 国产爆乳乱码女大生Av| 国产综合久久久久久鬼色| 国产无遮挡又黄又爽高潮| 亚洲一区二区三区激情在线 | 亚洲天堂激情av在线| 久久青草国产精品一区| 忘记穿内裤被同桌摸到高潮app| 国产精品久久无中文字幕|