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

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

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

      [WCF權(quán)限控制]模擬(Impersonation)與委托(Delegation)[上篇]

      由于服務(wù)操作是在寄宿進(jìn)程中執(zhí)行,在默認(rèn)的情況下,服務(wù)操作是否具有足夠的權(quán)限訪問某個(gè)資源(比如文件)決定于執(zhí)行寄宿進(jìn)程Windows帳號(hào)的權(quán)限設(shè)置,而與作為客戶端的Windows帳號(hào)無關(guān)。在有多情況下,我們希望服務(wù)操作執(zhí)行在基于客戶端的安全上下文中執(zhí)行,以解決執(zhí)行服務(wù)進(jìn)行的帳號(hào)權(quán)限不足的問題。這就涉及到一個(gè)重要的話題——模擬(Impersonation)與委托(Delegation)[實(shí)例程序源代碼從這里下載]

      目錄:
      一、從訪問令牌(Access Token)說起
      二、再談WindowsIdentity
      三、實(shí)例演示:通過身份模擬的方式讀取文件

      一、從訪問令牌(Access Token)說起

      當(dāng)我們以某個(gè)Windows帳號(hào)的名義成功登錄Windows的時(shí)候,操作系統(tǒng)會(huì)創(chuàng)建一個(gè)訪問令牌(Access Token)。訪問令牌不僅僅包括登錄用戶身份相關(guān)信息,還包括該用戶具有的權(quán)限信息,比如ACL(Access Control List)。當(dāng)我們開啟某個(gè)進(jìn)程的時(shí)候,該訪問令牌會(huì)自動(dòng)附加到該進(jìn)程上,作為其安全上下文重要的組成部分。我們也可以將訪問令牌作為進(jìn)程或者線程安全描述符的封裝。Windows下的訪問令牌主要具有如下兩種形式。

      • 主令牌(Primary Token):每一個(gè)進(jìn)程都具有一個(gè)唯一的主令牌,進(jìn)行通過主令牌被開啟;
      • 模擬令牌(Impersonation Token):在默認(rèn)的情況下,當(dāng)線程被開啟的時(shí)候,所在進(jìn)程的主令牌會(huì)自動(dòng)附加到當(dāng)前線程上,作為線程的安全上下文。而線程可以運(yùn)行在另一個(gè)非主令牌的訪問令牌下執(zhí)行,而這個(gè)令牌被稱為模擬令牌。而指定線程的模擬令牌的過程被稱為模擬。

      我們可以調(diào)用Win32函數(shù)LogonUser,通過輸入Windows帳號(hào)、密碼、域名以及認(rèn)證相關(guān)信息創(chuàng)建一個(gè)訪問令牌。LogonUser被調(diào)用的時(shí)候,會(huì)試圖進(jìn)行基于本機(jī)的登陸操作。訪問令牌會(huì)在認(rèn)證成功認(rèn)證的情況下被創(chuàng)建并返回。LogonUser的定義如下,輸入?yún)?shù)依次代表的含義分別是用戶名、域名(可選參數(shù))、密碼(明文)、登錄類型和登錄提供者。而創(chuàng)建的訪問令牌以輸出操作的形式返回。關(guān)于LogonUser函數(shù)的詳細(xì)說明,可以參考MSDN在線文檔。

         1: BOOL LogonUser(
         2:   __in      LPTSTR lpszUsername,
         3:   __in_opt  LPTSTR lpszDomain,
         4:   __in      LPTSTR lpszPassword,
         5:   __in      DWORD dwLogonType,
         6:   __in      DWORD dwLogonProvider,
         7:   __out     PHANDLE phToken
         8: );

      當(dāng)我們進(jìn)行模擬而試圖創(chuàng)建一個(gè)模擬令牌的時(shí)候,我們需要使用到另外一個(gè)重要的Win32函數(shù)DuplicateToken。顧名思義,該函數(shù)通過一個(gè)現(xiàn)有的令牌來“復(fù)制”一個(gè)新的令牌。DuplicateToken函數(shù)的定義如下面的代碼片斷所示。

         1: BOOL WINAPI DuplicateToken(
         2:   __in   HANDLE ExistingTokenHandle,
         3:   __in   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
         4:   __out  PHANDLE DuplicateTokenHandle
         5: );

      從上面給出的DuplicateToken函數(shù)的定義我們可以看出:除了傳入現(xiàn)有的訪問令牌作為輸入?yún)?shù)之外,還具有一個(gè)表示模擬級(jí)別的ImpersonationLevel的參數(shù)。模擬級(jí)別是一個(gè)非常重要的概念,它表示被復(fù)制的模擬令牌可以被使用的程度和訪問。模擬等級(jí)通過如下所示的SECURITY_IMPERSONATION_LEVEL枚舉表示。

         1: typedef enum _SECURITY_IMPERSONATION_LEVEL {
         2:   SecurityAnonymous,
         3:   SecurityIdentification,
         4:   SecurityImpersonation,
         5:   SecurityDelegation 
         6: } SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;

      四個(gè)枚舉項(xiàng),SecurityAnonymous、SecurityIdentification、SecurityImpersonation和SecurityDelegation分別代表如下四種模擬的等級(jí)。

      • 匿名(Anonymous):無法獲取有關(guān)客戶端的標(biāo)識(shí)信息,且無法模擬客戶端;
      • 識(shí)別(Identification):可以獲取有關(guān)客戶端的信息(如安全標(biāo)識(shí)符和特權(quán)),但是無法模擬客戶端;
      • 模擬(Impersonation):可以在本地模擬客戶端的安全上下文。,但無法在遠(yuǎn)程系統(tǒng)上模擬客戶端;
      • 委托(Delegation):可以在本地和遠(yuǎn)程系統(tǒng)上模擬客戶端的安全上下文。

      對(duì)于模擬級(jí)別,對(duì)于托管代碼的應(yīng)用編程接口中也具有一個(gè)匹配的枚舉TokenImpersonationLevel。如下面的代碼片斷所示,除了上述的四個(gè)對(duì)應(yīng)于具體模擬級(jí)別的枚舉項(xiàng)之外,TokenImpersonationLevel還有一個(gè)額外的枚舉值None,表示具體的模擬級(jí)別上為指定。

         1: public enum TokenImpersonationLevel
         2: {
         3:     None,
         4:     Anonymous,
         5:     Identification,
         6:     Impersonation,
         7:     Delegation
         8: }

      二、 再談WindowsIdentity

      關(guān)于模擬在托管代碼的實(shí)現(xiàn),我們不得不提我們之前已經(jīng)介紹過的類型WindowsIdentity。從某種意義上講,一個(gè)WindowsIdentity對(duì)象可以看成是對(duì)一個(gè)訪問令牌的封裝。WindowsIdentity直接為我們提供了模擬的功能。從下面給出的WindowsIdentity部分成員定義可以看到,它具有一個(gè)IntPtr類型的只讀屬性Token,實(shí)際上代表的就是我們上面介紹的訪問令牌。而我們可以通過直接指定這個(gè)訪問令牌創(chuàng)建一個(gè)WindowsIdentity對(duì)象。ImpersonationLevel表示訪問令牌的模擬級(jí)別。

         1: public class WindowsIdentity : IIdentity,...
         2: {
         3:     //其他成員
         4:     public WindowsIdentity(IntPtr userToken);
         5:     public virtual IntPtr Token { get; }
         6:     public TokenImpersonationLevel ImpersonationLevel { get; }
         7:  
         8:     
         9:     public virtual WindowsImpersonationContext Impersonate();
        10:     public static WindowsImpersonationContext Impersonate(IntPtr userToken);
        11: }

      對(duì)應(yīng)一個(gè)現(xiàn)有的WindowsIdentity對(duì)象,只要其訪問令牌的模擬級(jí)別為Impersonation或者Delegation,我們就能調(diào)用Impersonate方法模擬這個(gè)身份。此外WindowsIdentity還提供了靜態(tài)的Impersonate是我們可以直接根絕一個(gè)訪問令牌實(shí)施身份模式。一旦Impersonate方法被調(diào)用,基于被模擬身份的安全上下文會(huì)自動(dòng)附加到當(dāng)前線程。Impersonate方法返回的是一個(gè)WindowsImpersonationContext對(duì)象。如果需要將安全上下文恢復(fù)到模擬之前的狀態(tài),可以調(diào)用WindowsImpersonationContext的Undo方法。而WindowsImpersonationContext實(shí)現(xiàn)了IDisposable接口,Undo方法實(shí)際上也會(huì)在Dispose方法中被調(diào)用。WindowsImpersonationContext定義如下。

         1: public class WindowsImpersonationContext : IDisposable
         2: {    
         3:     public void Dispose();
         4:     public void Undo();
         5: }

      一般來說,只有某些特殊的操作(比如訪問一個(gè)受權(quán)限控制的文件)才需要在被模擬的身份下執(zhí)行。當(dāng)這些操作執(zhí)行完畢或者在執(zhí)行過程中拋出異常,我們都需要恢復(fù)線程安全上下文到被模式之前的狀態(tài)。所以正確的模擬編程應(yīng)該采用如下的方式。

         1: WindowsImpersonationContext impersonationContext = identity.Impersonate();
         2: try
         3: {
         4:     //在模擬身份下執(zhí)行的操作
         5: }
         6: catch (Exception ex)
         7: {
         8:     //異常處理
         9: }
        10: finally
        11: {
        12:     impersonationContext.Undo();
        13: }

      或者

         1: using (WindowsImpersonationContext impersonationContext = identity.Impersonate())
         2: { 
         3:    //在模擬身份下執(zhí)行的操作     
         4: }

      有一點(diǎn)需要注意的是:無論WindowsIdentity對(duì)象的模擬級(jí)別是什么,調(diào)用Impersonate方法都不會(huì)拋出異常。但是,只有當(dāng)模擬級(jí)別為Imperation或者Delegation的情況下,采用真正使用被模擬的身份進(jìn)行安全資源的訪問。

      三、實(shí)例演示:通過身份模擬的方式讀取文件

      為了讓讀者對(duì)身份模式的作用和實(shí)現(xiàn)具有一個(gè)深刻的認(rèn)識(shí),我們來演示一個(gè)簡單的實(shí)例。在這個(gè)實(shí)例中,我們將通過ACL設(shè)置一個(gè)文件的讀取權(quán)限,然后演示針對(duì)不同Windows帳號(hào)進(jìn)行模擬的情況下,是否能夠正常讀取該文件。

      我們需要?jiǎng)?chuàng)建了兩個(gè)本機(jī)的Windows帳戶Foo和Bar(密碼為Password)。然后你在某個(gè)公共的目錄下(比如D:\盤)創(chuàng)建一個(gè)簡單的文本(比如impersonationTest.txt)。然后賦予帳號(hào)Foo對(duì)該文件的讀取權(quán)限,但拒絕帳號(hào)Bar讀取該文件。

      然后我們創(chuàng)建一個(gè)簡單的控制臺(tái)應(yīng)用作為演示程序。在默認(rèn)創(chuàng)建的Program類中,定義如下一個(gè)CreateWindowsIdentity靜態(tài)方法。該方法通過輸入用戶名、密碼和模擬級(jí)別創(chuàng)建相應(yīng)的WindowsIdentity。在CreateWindowsIdentity方法內(nèi)部實(shí)際上是直接調(diào)用了上面介紹的兩個(gè)Win32函數(shù)LogonUser和DuplicateToken。

         1: class Program
         2: {
         3:     //其他成員
         4:     public const int LOGON32_PROVIDER_DEFAULT = 0;
         5:     public const int LOGON32_LOGON_INTERACTIVE = 2;
         6:  
         7:     [DllImport("advapi32.dll", SetLastError = true)]
         8: public static extern bool LogonUser(string userName, string domainName, string password, int logonType, int loggonProvider, ref IntPtr token);
         9:  
        10:     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        11: public extern static bool DuplicateToken(IntPtr existingToken, int imperonationLevel, ref IntPtr newToken);
        12:  
        13:     public static WindowsIdentity CreateWindowsIdentity(string userName, string password, TokenImpersonationLevel tokenImpersonationLevel)
        14:     {
        15:         IntPtr token = IntPtr.Zero;
        16:         IntPtr duplicateToken = IntPtr.Zero;
        17:         if (LogonUser(userName, string.Empty, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token))
        18:         {
        19:             int impersonationLevel;
        20:             switch (tokenImpersonationLevel)
        21:             {
        22:                 case TokenImpersonationLevel.Anonymous:
        23:                     { impersonationLevel = 0; break; }
        24:                 case TokenImpersonationLevel.Impersonation:
        25:                     { impersonationLevel = 2; break; }
        26:                 case TokenImpersonationLevel.Delegation:
        27:                     { impersonationLevel = 3; break; }
        28:                 default:
        29:                     { impersonationLevel = 1; break; }
        30:             }
        31:             if (DuplicateToken(token, impersonationLevel, ref duplicateToken))
        32:             {
        33:                 return new WindowsIdentity(duplicateToken);
        34:             }
        35:             else
        36:             {
        37:                 throw new InvalidOperationException(string.Format("創(chuàng)建模擬令牌失敗 (錯(cuò)誤代碼: {0}) ", Marshal.GetLastWin32Error()));
        38:             }
        39:         }
        40:         else
        41:         {
        42:             throw new InvalidOperationException(string.Format("用戶登錄失敗 (錯(cuò)誤代碼: {0}) ", Marshal.GetLastWin32Error()));
        43:         }
        44:     }        
        45: }

      然后我們定義如下一個(gè)靜態(tài)的ReadFile方法。在這個(gè)方法中,我們根據(jù)傳入的用戶名和密碼調(diào)用上述的CreateWindowsIdentity方法創(chuàng)建相應(yīng)的WindowsIdentity。然后模擬該用戶進(jìn)行文件的讀取。在成功讀取和拋出異常的情況下分別輸出相應(yīng)的指示性文字。在Main方法中,分別傳入傳入賬號(hào)Foo和Bar以及相應(yīng)的密碼對(duì)該方法進(jìn)行調(diào)用。從輸出的結(jié)果可以看出,在模擬帳號(hào)Foo時(shí),文件被成功讀取,而在模擬帳號(hào)Bar的時(shí)候卻失敗了。這和測試文件的ACL設(shè)置時(shí)一致的。

         1: public static void ReadFile(string userName, string password)
         2: {
         3:     try
         4:     {
         5:         WindowsIdentity identity = CreateWindowsIdentity(userName, password, TokenImpersonationLevel.Impersonation);
         6:         using (WindowsImpersonationContext context = identity.Impersonate())
         7:         {
         8:             Console.WriteLine("當(dāng)前用為:{0}", WindowsIdentity.GetCurrent().Name);
         9:             File.ReadAllText("D:\\impersonationTest.txt");
        10:             Console.WriteLine("成功讀取文件內(nèi)容...");
        11:         }
        12:     }
        13:     catch
        14:     {
        15:         Console.WriteLine("讀取文件失敗...");
        16:     }
        17: }
        18: static void Main(string[] args)
        19: {
        20:     ReadFile("Foo", "Password");
        21:     ReadFile("Bar", "Password");
        22: }

      輸出結(jié)果(Jinnan-PC為我本機(jī)的機(jī)器名):

         1: 當(dāng)前用戶為:Jinnan-PC\Foo
         2: 成功讀取文件內(nèi)容...
         3: 當(dāng)前用戶為:Jinnan-PC\Bar
         4: 讀取文件失敗...
      posted @ 2011-07-03 15:00  Artech  閱讀(8177)  評(píng)論(11)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲成在人天堂一区二区| 精品久久久久久无码人妻蜜桃| 亚洲人妻系列中文字幕| 给我播放片在线观看| 起碰免费公开97在线视频| 天天做天天爱夜夜爽导航| 国产精品人妻系列21p| 亚洲天堂网色图伦理经典| 江永县| 国产精品永久免费成人av| 白丝乳交内射一二三区| 国产精品视频午夜福利| 亚洲国产无套无码av电影| 女同AV在线播放| 中文字幕在线日韩| 国产精品欧美福利久久| 精品久久精品久久精品久久| 精品国产大片中文字幕| 40岁大乳的熟妇在线观看| 国产精品午夜福利小视频| 日本不卡三区| 国产中文三级全黄| 三亚市| 在线成人国产天堂精品av| 亚洲日韩av在线观看| 九九热在线观看视频精品| 国产日韩精品秘 入口| 国产成人精品中文字幕| 亚洲国产码专区在线观看| yw尤物av无码国产在线观看| 亚洲人成自拍网站在线观看| 少妇久久久被弄到高潮| 狠狠色丁香婷婷综合尤物| 宜阳县| 婷婷色综合成人成人网小说| 偷拍精品一区二区三区| 国产午夜精品福利91| 国产高清一区二区三区视频| 亚洲色丰满少妇高潮18p| 免费无码一区无码东京热| 亚洲一区二区三区人妻天堂|