11.3 使用者环境.htm
来自「Windows2000后台服务程序开发手册」· HTM 代码 · 共 468 行 · 第 1/3 页
HTM
468 行
size=2>值</FONT> </TH>
<TH style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
size=2>叙述</FONT></TH></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>SecurityAnonymous</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>用SecurityAnonymous模拟等级建立的权杖,不能用模拟建立一个处理程序。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>SecurityIdentification</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>用此模拟等级建立的权杖,只能被用来作为身分识别的方法。权杖的使用者及群组可以被查询,但是权杖不能与模拟一起使用,或在呼叫CreateProcessAsUser函数中使用。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>SecurityImpersonation</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>这个模拟等级建立一个具有完全功能的权杖,它不但可以被查询,而且可以用来透过模拟执行程序代码。权杖在线程可模拟之前,必须是个模拟权杖。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>SecurityDelegation</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>有SecurityDelegation模拟等级的权杖,可以被用来存取网路来源。这被称为<FONT
style="LINE-HEIGHT: 25px" face=arial color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 委派 </B></FONT>,而且在连接次要的伺服端里,可让伺服端变成代表它客户的客户端。Windows
NT 4.0及较早的版本不支援委派。Windows
2000也是,但是它需要委派在服务器试图建立一个委派类型的权杖时被允许。</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>TokenType可以是TokenPrimary或者TokenImpersonation,都是TOKEN_TYPE列举型别的成员。最后一个参数phNewToken,它会收到新权杖的handle。当您用完此物件时,请记得呼叫CloseHandle关闭它。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>假如DuplicateTokenEx传回FALSE,则表示函数已经执行失败。它失败的原因通常会是原始权杖上的存取权不够(有关存取控制及存取权利的完整讨论,请参阅 </FONT><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2><A
style="LINE-HEIGHT: 25px"
href="http://e-msbooks.com/relaunch/XML/paser.asp?src=957-2085-84-0_210.xml#"
target=_new>第十章</A> )。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>Windows先前的版本中,为了代表客户端行为的目的而在伺服端机器上建立的权杖被称为网路权杖,它通常拥有SecurityImpersonation模拟等级。这些权杖不包含信任成员凭证的副本,并且不能被用来存取建立此权杖之机器外的资源。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>然而,Windows
2000使用Kerberos安全性协定以支援SecurityDelegation模拟等级(在第十二章中讨论)。现在要拥有一个不限制存取本地端机器的网路权杖是可能的。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7
size=4><B style="LINE-HEIGHT: 25px">使用LogonUser取得权杖<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>现在您已经知道从程序中取得权杖,以及如何使用任一权杖建立处理程序的方法。然而我们尚未讨论当您只有使用者名称及密码,要如何撷取权杖handle的方法。您可以经由呼叫LogonUser来达成它:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL LogonUser( <BR> PTSTR pszUsername, <BR> PTSTR pszDomain, <BR> PTSTR pszPassword, <BR> DWORD dwLogonType, <BR> DWORD dwLogonProvider, <BR> PHANDLE phToken);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>pszUsername及pszDomain参数指出您想要收到的使用者名称及网域的权杖。您可以传递句点字元(「.」)给pszDomain参数,使它只搜寻本机系统的帐户资料库。假如您传递NULL给pszDomain参数,则本机系统会在信任的网域中搜寻使用者。第叁个参数pszPassword,是这个帐户的密码。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>LogonUser的dwLogonType参数,会向系统描述权杖如何被使用以及您想收到的权杖类型。表格11-4中列出您可以传递给dwLogonType参数的值。</FONT></P>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE border=0>
<TBODY style="LINE-HEIGHT: 25px">
<TR>
<TD align=middle><FONT style="LINE-HEIGHT: 25px" face=arial
color=#000000 size=2><FONT style="LINE-HEIGHT: 25px"
face=arial color=#3e80d7 size=2><B
style="LINE-HEIGHT: 25px"> 表格11-4 </B></FONT>您可以传递给LogonUser的dwLogonType参数的值</FONT></TD></TR></TBODY></TABLE></CENTER>
<CENTER style="LINE-HEIGHT: 25px">
<TABLE border=1>
<TBODY style="LINE-HEIGHT: 25px">
<TR>
<TH style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
size=2>值</FONT> </TH>
<TH style="LINE-HEIGHT: 25px"><FONT style="LINE-HEIGHT: 25px"
size=2>叙述</FONT></TH></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px" size=2>LOGON32_LOGON_
INTERACTIVE</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否有SE_INTERACTIVE_LOGON_NAME权限存在。假如使用者没有被指派这个权限,则LogonUser执行将会失败。此外,用这个登入收到的权杖会与系统一起快取。这意味着本机系统可能会与验证机器失去联络,但是将来使用快取凭证呼叫LogonUser时,仍旧会执行成功。LogonUser将传回一个主要的权杖。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px" size=2>LOGON32_LOGON_
BATCH</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_BATCH_LOGON_NAME权限。假如使用者没有这个权限,则LogonUser将执行失败。用这个登入类型而收到的权杖不会被快取,它会提高LogonUser的效能并使这个登入类型适合高效能的服务器。LogonUser会传回一个主要的权杖。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>LOGON32_LOGON_NETWORK</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_NETWORK_LOGON_NAME权限。假如使用者没有这个权限,则LogonUser将失败。用这个登入类型而收到的权杖不会被快取。另外,这个权杖将会是个模拟权杖及「网路权杖」。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px" size=2>LOGON32_LOGON_
NETWORK_ CLEARTEXT</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>跟LOGON32_LOGON_NETWORK登入类型一样,这个登入类型会检查讨论中帐户的SE_NETWORK_LOGON_NAME帐户权利。然而,不像LOGON32_LOGON_NETWORK一般,当preserving信任成员凭证的副本使用产生的权杖存取网路时,这个登入类型会传回一个模拟权杖。该权杖必需在它可以被用来呼叫CreateProcessAsUser前,即被复制成主要的权杖
。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px" size=2>LOGON32_LOGON_
NEW_CREDENTIALS</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>这个是Windows2000的新结构登入类型。它要求您使用LOGON32_PROVIDER_WINNT50作为呼叫LogonUser中的dwLogonProvider值。这个登入类型会复制呼叫线程的程序权杖,并且将次要的身分识别加到权杖中。这个次要的身分识别将是所有网路存取权杖的身分识别,本地端机器的权杖身分识别仍然会跟原始权杖一样。这使得LOGON32_LOGON_NEW_凭证为唯一的,因为它使用现行的权杖,并用额外的凭证建立一个新的权杖。有关这个登录类型的范例,请看Windows
2000提供的RunAs.exe公用程序。<BR style="LINE-HEIGHT: 25px"><FONT
style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>「/NetOnly」参数会使用LOGON32_LOGON_NEW_CREDENTIALS登入类型为新的程序建立一个权杖。这个被产生的权杖是一个主要权杖。</FONT></FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>LOGON32_LOGON_SERVICE</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_SERVICE_LOGON_NAME权限。假如使用者没有被指派这个权限,LogonUser将执行失败。如果机器与验证代理程序失去联络时,为了将来还能呼叫LogonUser,这个权杖会被快取。LogonUser会传回一个主要权杖。</FONT></TD></TR>
<TR>
<TD><FONT style="LINE-HEIGHT: 25px" size=2>LOGON32_LOGON_
UNLOCK</FONT></TD>
<TD><FONT style="LINE-HEIGHT: 25px"
size=2>这个登入类型被GINA用来处理未锁定的工作站。假如这个系统的稽核被启动时,可用这个登入类型呼叫LogonUser,以便在事件日志中建立一个项目。所产生的权杖是个主要权杖。</FONT></TD></TR></TBODY></TABLE></CENTER>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>作为一个开发人员或网路管理员,您可以绑紧您的安全性,并且使系统更安全来预防建立了只能与LOGON32_LOGON_SERVICE或LOGON32_
LOGON_INTERACTIVE类型一起作用的使用者帐户的误用。例如,您只能分别授予SE_SERVICE_LOGON_NAME或SE_INTERACTIVE_LOGON_NAME权限。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=Arial color=#3e77d7 size=3
Black><B style="LINE-HEIGHT: 25px">说明</B></FONT> </P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>尽管登入类型,如LOGON32_LOGON_SERVICE及LOGON32_LOGON_INTERACTIVE,要求了不同的权限,但是实际上它们却不能彻底地产生不同的权杖(权杖之间主要的不同是权杖群组中存在SID,它指出登录使用什么类型,登录的来源也有不同)。要求不同的权限可让系统提供额外的验证等级,而不用使权杖的结构复杂化。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>用LOGON32_LOGON_BATCH或LOGON32_LOGON_SERVICE建立的权杖仍旧可以执行与使用者的互动程序,及建立视窗和其他GUI物件。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>然而,当系统建立一个如服务一样执行的处理程序时,它使用的权杖是用LOGON32_LOGON_SERVICE登入类型登入的。而当系统以互动方式让使用者登入系统时,它会使用LOGON32_LOGON_INTERACTIVE登入类型。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您传递给dwLogonProvider的值,决定要使用哪个方法验证传递到LogonUser的凭证。除非您正在使用LOGON32_LOGON_NEW_CREDENTIALS登入类型,否则您就应该传递LOGON32_PROVIDER_DEFAULT给所有使用的LogonUser。在这种情形中,您应该传递LOGON32_PROVIDER_WINNT50的值给dwLogonProvider参数。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>您会经由LogonUser的phToken参数收到新权杖的handle。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>假如系统在验证凭证时执行成功,LogonUser函数将传回TRUE,假如失败则传回FALSE。呼叫GetLastError将传回失败的原因。当LogonUser执行失败时,会产生叁种常见的错误:即ERROR_LOGON_FAILURE、ERROR_LOGON_
TYPE_NOT_GRANTED及ERROR_PRIVILEGE_NOT_HELD。当GetLastError传回ERROR_LOGON_FAILURE时,表示无法识别传递到LogonUser的凭证。假如GetLastError传回ERROR_LOGON_TYPE_NOT_GRANTED,则表示要求的帐户没有要求登入类型的适当帐户权利。错误程序代码ERROR_PRIVILEGE_NOT_HELD暗示呼叫LogonUser的程序没有被授予SE_TCB_NAME权限。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>本机帐户预设为拥有此授予的权限,系统中没有预设其他信任成员拥有这个权限。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您用完这个权杖后,呼叫属于物件的CloseHandle以关闭它。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您在呼叫LogonUser时,您会要求系统为您建立一个权杖。您可以呼叫CreateProcessAsUser及模拟来使用这个权杖,这是下一节的主题。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7
size=4><B style="LINE-HEIGHT: 25px">模拟(Impersonation)<BR
style="LINE-HEIGHT: 25px"> </B></FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>当您在Windows中编写服务器软件时,可以选择建立一个代表客户端的处理程序以执行客户端的请求。然而,为每个客户端建立一个处理程序并不是可调整的技巧。模拟是这个问题的解决办法,因为它让个别的线程在您的客户端安全性环境下执行任一时间长度,然而当它完成,就会回复到程序的安全性环境。模拟可以极有效率的使用并且以可调整的方式完成。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>我非常喜爱模拟-系统会为您处理琐碎的细节,而且它经由呼叫ImpersonateLoggedOnUser而被简单地实作。这真的是很棒,因为它保证线程在客户端的安全性环境下执行。有什么更好的方法可保证您不会意外地让客户端导致服务经由本机帐户而滥用授予的可怕权利?以下是ImpersonateLoggedOnUser函数的定义:</FONT></P>
<DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT
style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">BOOL ImpersonateLoggedOnUser( HANDLE hToken);</PRE></FONT></DIV>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>假如传递给hToken参数的权杖是TokenPrimary类型,则ImpersonateLoggedOnUser会建立一个与TokenImpersonation类型完全一样的权杖,并将它分派到呼叫的线程。假如原始的权杖已经是个模拟权杖,则权杖会被直接分派给线程。在第一个情形下,呼叫的线程必须拥有对权杖的TOKEN_QUERY及TOKEN_DUPLICATE存取权。第二个情况中,则只需要TOKEN_QUERY存取权。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>假如ImpersonateLoggedOnUser执行成功,它会传回TRUE。否则您的服务应该呼叫GetLastError函数,以找出失败的原因。</FONT></P>
<P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000
size=2>传递给ImpersonateLoggedOnUser的权杖可以是经由呼叫LogonUser、DuplicateTokenEx、OpenThreadToken,或是目前为止我们所讨论过的任何其他类似函数收到的权杖。它也可以经由某些其他方法撷取的权杖(本书将扼要地讨论一些方法)。在执行成功后,多数经由模拟线程呼叫的安全函数能识别由权杖代表的新安全性。</FONT></P>
<HR style="LINE-HEIGHT: 25px">
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?