12.2.3 安全连接.htm

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

HTM
395
字号
      <TABLE cellSpacing=5 cellPadding=0 width="100%" align=center border=0>
        <TBODY>
        <TR>
          <TD vAlign=top>
            <TABLE cellSpacing=0 cellPadding=10 align=left border=0>
              <TBODY>
              <TR>
                <TD></TD></TR></TBODY></TABLE>
            <DIV class=content id=ArticleBody 
            style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
            <P class=content>
            <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-8&nbsp;</B></FONT>可让CertOpenStore之Flags参数选择的值</FONT></TD></TR></TBODY></TABLE>
            <CENTER></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>CERT_SYSTEM_STORE_CURRENT_SERVICE</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>指出现行服务执行所在地的帐户存放档</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>CERT_SYSTEM_STORE_CURRENT_USER</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>指出呼叫程序代码之当前使用者帐户存放档</FONT></TD></TR>
              <TR>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                  size=2>CERT_SYSTEM_STORE_LOCAL_MACHINE</FONT></TD>
                <TD><FONT style="LINE-HEIGHT: 25px" 
                size=2>指出本地端机器的存放档</FONT></TD></TR></TBODY></TABLE></CENTER>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>pvPara参数提供用来寻找存放档的特殊资讯。对于系统存放档,您应该传递指出存放档名称的字串。如果您使用个人存放档,则应该使用文字「MY」。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>若您传递了一个无法被系统识别的名称,系统将为您建立这个存放档。这会是个建立机器上之逻辑群组凭证的便利方法。CertOpenStore函数会传回HCERTSTORE变数值,它是个凭证存放档的handle。当您使用完凭证存放档时,应该使用CertCloseStore函数关闭这个handle:</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 WINAPI CertCloseStore( <BR> HCERTSTORE hCertStore, <BR> DWORD dwFlags);</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>通常会传递0给dwFlags值。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#3e74d7 
            size=3><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>凭证中包含丰富的资讯数量,CryptoAPI可让您使用储藏在凭证中的任何资讯来查询凭证。然而,一旦您在处理查询时没有经过明确的设定,便会使凭证中的大部分资讯不具唯一性。通常会透过凭证的常见名称参考它们,所以您应该用它们的常见名称来查询。</FONT></P>
            <P><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;属性&nbsp;</B></FONT>。在存放档中查询凭证时,可以使用一个或多个属性做为查询的准则。您可以为每个属性建立一个结构阵列,然后把它们传递到CertFindCertificateInStore函数中:</FONT></P>
            <DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT 
            style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">PCCERT_CONTEXT WINAPI CertFindCertificateInStore( <BR> HCERTSTORE hCertStore, <BR> DWORD dwCertEncodingType, <BR> DWORD dwFindFlags, <BR> DWORD dwFindType, <BR> const void *pvFindPara, <BR> PCCERT_CONTEXT pPrevCertContext);</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>hCertStore参数是个开启存放档的handle,其中包含凭证。dwCertEncoding 
            Type参数应该一直是X509_ASN_ENCODING|PKCS_7_ASN_ENCODING值。大部分的情况下,您应该传递0给dwFindFlags参数,请查阅《Platform 
            SDK》文件以取得更详细的资讯。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>dwFindType参数指出您想要用来搜寻凭证的方法。如果您要经由一个或多个凭证的属性搜寻凭证时,应该传递CERT_FIND_SUBJECT_ATTR值。</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>您也可以使用许多其他的方法去搜寻凭证。例如,您确信为开启存放档中唯一的凭证时,可以传递CERT_FIND_ANY给dwFindType参数。搜寻的选项内容可在《Platform 
            SDK》文件中查询。在本章中,我们会集中在常使用的方法上。</FONT></P>
            <HR style="LINE-HEIGHT: 25px">

            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>您可以传递实际的搜寻准则给pvFindPara参数。假如您要经由它的属性来查询,则可以使用CERT_FIND_SUBJECT_ATTR标记搜寻凭证,您应传递一个指向CERT_RDN结构的指标给这个参数。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>CertFindCertificateInStore可以被用来列举存放档中的凭证。pPrevCertContext参数指出最后取得的内容。您应该传递NULL给第一个凭证的内容,或当您在查询唯一的凭证时也应传递NULL给它。</FONT></P>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>假如您的搜寻执行成功时,CertFindCertificateInStore将传回指向凭证内容结构的指标。当您用完这个结构后,必须使用CertFreeCertificateContext函数释放它:</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 WINAPI CertFreeCertificateContext( <BR> PCCERT_CONTEXT pCertContext);</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>当在呼叫CertFindCertificateInStore函数时,您应传递CERT_RDN结构以做为pvFindPara结构值,其定义如下:</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 _CERT_RDN { <BR> DWORD cRDNAttr; <BR> PCERT_RDN_ATTR rgRDNAttr; <BR>} CERT_RDN;</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>cRDNAttr成员指出被您用来搜寻凭证的属性数量。rgRDNAttr成员是个指向已填满属性资讯的CERT_RDN_ATTR结构阵列指标。以下是CERT_RDN_ATTR的定义:</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 _CERT_RDN_ATTR { <BR> PSTR pszObjId; <BR> DWORD dwValueType; <BR> CERT_RDN_VALUE_BLOB Value; <BR>} CERT_RDN_ATTR;</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>这个结构设计得非常有弹性,因为它必须包含许多能在凭证中制造属性的资料类型。pszObjId成员是我们非常关心的属性ID。对于凭证的常见名称,您应该使用szOID_COMMON_NAME值。dwValueType成员指出这个值的资料类型。应设定常见名称的值为CERT_RDN_PRINTABLE_STRING(注意,您必须一直使用ANSI字串)。</FONT></P>
            <P><FONT style="LINE-H: 25px" face=arial color=#000000 
            size=2>Value成员是个Blob结构,它包含了两个成员:即cbData及pbData,分别是资料的大小及指向资料的指标。</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>有些属性类型及资料类型可在《Platform 
            SDK》文件中找到详细的内容。如果您想要了解pupulate的结构,可能必须使用另一个方法来搜寻凭证,因为文件中并没有描述。例如,您可以开启凭证并查看它的RDN值,以便将来可以使用类似的资料查询凭证。</FONT></P>
            <HR style="LINE-HEIGHT: 25px">

            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>以下的程序代码范例显示了截至目前为止已讨论过的凭证函数用法。它会开启本地端机器的个人存放档,并且查询名称为「Jason’s 
            Test Certificate」的凭证。</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>尽管「Jason’s Test 
            Certificate」是一个绝对合法的凭证名称,但并不代表一般的用法。通常凭证会依照服务器的网路位置命名,这样一来,客户端软件便可以把凭证的网路位置名称与它试图初始之安全工作阶段的网路位置作比较。</FONT></P>
            <HR style="LINE-HEIGHT: 25px">

            <DIV style="LINE-HEIGHT: 25px; BACKGROUND-COLOR: #d7d7d7"><FONT 
            style="LINE-HEIGHT: 25px" face=Arial size=3><PRE style="LINE-HEIGHT: 25px">// 开启本地端机器的个人凭证存放档 <BR>HCERTSTORE hMyCertStore = <BR> CertOpenStore(CERT_STORE_PROV_SYSTEM_A, <BR>&nbsp;&nbsp;X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, <BR>&nbsp;&nbsp;0, <BR>&nbsp;&nbsp;CERT_SYSTEM_STORE_LOCAL_MACHINE, <BR>&nbsp;&nbsp;"MY"); <BR>if(hMyCertStore==NULL){ <BR> // 错误 <BR>} <BR>// 填入凭证名称的属性结构 <BR>PSTR pszCommonName = "Jason’s Test Certificate"; <BR>CERT_RDN_ATTR certRDNAttr[1]; <BR>certRDNAttr[0].pszObjId = szOID_COMMON_NAME; <BR>certRDNAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING; <BR>certRDNAttr[0].Value.pbData = (PBYTE)pszCommonName; <BR>certRDNAttr[0].Value.cbData = lstrlen(pszCommonName); <BR>CERT_RDN certRDN = {1, certRDNAttr}; <BR>// 搜寻凭证的内容 <BR>PCCERT_CONTEXT pCertContext = <BR> CertFindCertificateInStore(hMyCertStore, <BR>&nbsp;&nbsp;X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, <BR>&nbsp;&nbsp;0, <BR>&nbsp;&nbsp;CERT_FIND_SUBJECT_ATTR, <BR>&nbsp;&nbsp;&amp;certRDN, <BR>&nbsp;&nbsp;NULL); <BR>if (pCertContext == NULL){ <BR> // 错误 <BR>}</PRE></FONT></DIV>
            <P><FONT style="LINE-HEIGHT: 25px" face=arial color=#000000 
            size=2>这个执行查询凭证工作的程序代码相当简短,不过您可能会对程序代码之后所显示的新概念感到惊讶。假如服务器向客户端验证它自己,而不考虑客户端验证时,先前的程序代码即是服务器所要担心的所有凭证程序代码。剩下的工作交由SSL处理,我们将立即讨论这部份。</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=#3e74d7 
            size=3><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>您的软件通常会读取经由使用SSL远端原则所接收的凭证资讯。然而,情形并非一直如此,您的软件可以从CertFindCertificateInStore函数接收到的凭证中读取资讯。这两个方法是相同的,您将从SSL传回的PCCERT_CONTEXT结构或是CryptoAPI开始。以下是系统从凭证读取属性资讯时必须采用的步骤:</FONT></P><FONT 
            style="LINE-HEIGHT: 25px" face=arial color=#000000 size=2>
            <OL style="LINE-HEIGHT: 25px">
              <LI style="LINE-HEIGHT: 25px">将凭证的「主要(subject)」Blob解密。 
              <LI style="LINE-HEIGHT: 25px">找到您想读取的RDN属性。 

⌨️ 快捷键说明

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