12.1.3 安全连接.htm

来自「Windows2000后台服务程序开发手册」· HTM 代码 · 共 664 行 · 第 1/4 页

HTM
664
字号
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>我们用NTLM来举例说明。请看&nbsp;</FONT></A><FONT 
            style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2><A 
            style="LINE-HEIGHT: 25px" 
            href="http://www.acejoy.com/doc/serverside/12.htm#631_1" 
            target=_new>图12-1</A>&nbsp;中,NTLM在客户端及服务器之间需要叁个通讯行程:验证请求、挑战转送、回传回应。当您使用NTLM验证SSPI程序代码时,它会重覆InitializeSecurityContext回圈二次,并要求您的客户端与服务器通讯叁次。这些回圈直接与&nbsp;<A 
            style="LINE-HEIGHT: 25px" 
            href="http://www.acejoy.com/doc/serverside/12.htm#631_1" 
            target=_new>图12-1</A>&nbsp;中所见的通讯行程有关。然而,如果您使用Kerberos验证的方式,SSPI将只需要一个动作即可通过整个SSPI程序。这可能会使人感到惊讶,请再浏览图12-2的Kerberos通讯协定一次,其显示出客户端与服务器间只通讯一次(假如需要彼此验证,客户端会与服务器通讯二次)。依据SSPI顺序的程序代码流程会反映出此部份的内容。</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>SSPI只对您的软件揭露客户端及服务器之间的通讯。任何与第叁方的通讯,例如KDC或DC,会在SSPI的背景处理。</FONT></P>
            <HR style="LINE-HEIGHT: 25px">

            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>好了,我们已经谈论够多关于这部份的内容了。现在让我们看看用来实作SSPI程序代码的函数部份。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e72d7 
            size=4><B style="LINE-HEIGHT: 25px">取得凭证<BR 
            style="LINE-HEIGHT: 25px">  </B></FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>开发SSPI程序代码的第一步是向SSPI建立您自己的凭证,以及您想使用的安全性通讯协定。您可以呼叫AcquireCredentialsHandle来达成:</FONT></P>
            <DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT 
            style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">SECURITY_STATUS AcquireCredentialsHandle( <BR> SEC_CHAR* pszPrincipal, <BR> SEC_CHAR* pszPackage, <BR> ULONG lCredentialUse, <BR> PLUID pvLogonId, <BR> PVOID pAuthData, <BR> PVOID pGetKeyFn, <BR> PVOID pvGetKeyArgument, <BR> PCredHandle phCredential, <BR> PtimeStamp ptsExpiration);</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>请注意,AcquireCredentialsHandle函数中有一些新的资料类型。SEC_CHAR资料类型是SSPI函数使用的字串类型,而且它会转换成一个TCHAR的类型。SECURITY_STATUS类型是所有SSPI函数传回的错误值。&nbsp;<A 
            style="LINE-HEIGHT: 25px" 
            href="http://www.acejoy.com/doc/serverside/12.htm#631_2" 
            target=_new>表12-6</A>&nbsp;显示了一些一般定义的错误值。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>因为必须传递的参数数量很多,使得AcquireCredentialsHandle看起来可能会令人怯步,但是您通常可以传递NULL给它们。pszPrincipal参数是您所撷取凭证之handle的原则名称或实体名称。您通常可以传递NULL给这个值,以指出现行线程(或程序)权杖的身分识别。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>您可以传递一串字串给pszPackage参数,表明您想使用的安全性通讯协定。《Platform 
            SDK》中有代表Kerberos、NTLM、协商及SSL的对应字串名称值。表12-4中列出了这些值。</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">&nbsp;表12-4&nbsp;</B></FONT>可以传递给AcquireCredentialsHandle之pszPackage参数的安全性封装值</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>MICROSOFT_KERBEROS_NAME</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>Kerberos安全性支援提供者</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                size=2>NTLMSP_NAME</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                size=2>NTLM安全性支援提供者</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                size=2>NEGOSSP_NAME</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
              size=2>协商安全性支援提供者</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
size=2>UNISP_NAME</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>SChannel安全性支援提供者(SSL)</FONT></TD></TR></TBODY></TABLE></CENTER>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>您应该传递表12-4中定义的其中一个值给pszPackage参数。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>lCredentialsUse参数可以被设定为表12-5中的其中一个值,它指出如何使用特定的凭证handle。</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">&nbsp;表12-5&nbsp;</B></FONT>可以传递给AcquireCredentialsHandle之lCredentialUse的参数值,指出凭证如何被使用</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>SECPKG_CRED_INBOUND</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>您的软件将验证进入的使用者内容(这是服务器的一般设定)。</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>SECPKG_CRED_OUTBOUND</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>您的软件会被远端的那方验证(这是客户端的一般设定)。</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>SECPKG_CRED_BOTH</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>这个值指出您凭证handle的两个用法,是支援彼此验证服务器的一般设定。</FONT></TD></TR></TBODY></TABLE></CENTER>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>pvLogonId参数被呼叫AcquireCredentialsHandle的文件系统服务所使用,您应该传递NULL给它。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>pAuthData参数被用来支援您要用来建立凭证handle的特定协定凭证。假如您传递NULL值给它,则会传回一个凭证handle给您权杖的凭证。NTLM、Kerberos及协商安全性提供者也可让您传递一个指向以下所列之结构实体指标给pAuthData参数:</FONT></P>
            <DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT 
            style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">typedef struct { <BR> SEC_CHAR* User; <BR> ULONG UserLength; <BR> SEC_CHAR* Domain; <BR> ULONG DomainLength; <BR> SEC_CHAR* Password; <BR> ULONG PasswordLength; <BR> ULONG Flags; <BR>} SEC_WINNT_AUTH_IDENTITY;</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>假如您使用了 
            _SEC_WINNT_AUTH_IDENTITY结构并且传递它给pAuthData参数,您应该将结构设定如下:</FONT></P>
            <DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT 
            style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">SEC_WINNT_AUTH_IDENTITY authIdentity = {0}; <BR>authIdentity.User = TEXT("UserName"); <BR>authIdentity.UserLength = lstrlen(TEXT("UserName")); <BR>authIdentity.Domain = TEXT("Domain"); <BR>authIdentity.DomainLength = lstrlen(TEXT("Domain")); <BR>authIdentity.Password = TEXT("Password"); <BR>authIdentity.PasswordLength = lstrlen(TEXT("Password")); <BR>authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>当然,您应该使用实际的使用者名称及网域和密码值。假如您用ANSI代替Unicode编译,则您应该指派SEC_WINNT_AUTH_IDENTITY_ANSI值给结构中的Flags成员。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>AcquireCredentialsHandle函数可让您定义回呼(Callback)函数,它用来建立与SSPI一起使用的金钥。不需要这项特色的大多数软件可以传递NULL给pGetKeyFn及pvGetKeyArgument参数。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>您应该传递PcredHandle变数的位址给hCredential参数。AcquireCredentialsHandle函数会传回最近建立的凭证handle给这个变数。最后,您应该传递TimeStamp结构的位址给ptsExpiration参数。</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>有几个SSPI函数会传回TimeStamp结构。这个结构可与使用FileTimeToSystemTime函数的标准FILETIME结构交换。 
            所有SSPI函数应该传回本地时间的TimeStamp(或FILETIME)资讯。有关FILETIME结构的更多资讯,请参阅《Platform 
            SDK》文件的内容。</FONT></P>
            <HR style="LINE-HEIGHT: 25px">

            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>就像所有的SSPI函数一样,当AcquireCredentialsHandle执行成功时,它会传回SEC_E_OK。表12-6中列出了一些相关的SECURITY_STATUS值。</FONT></P><A 
            style="LINE-HEIGHT: 25px" name=631_2>
            <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">&nbsp;表12-6&nbsp;</B></FONT>相关的SECURITY_STATUS值</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>SEC_E_OK</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
size=2>全部执行成功。</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>SEC_E_NOT_OWNER</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>函数的呼叫者不是要求凭证的拥有者。</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>SEC_E_INVALID_HANDLE</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?