使用 BinarySecurityToken 通过 X.509 证书保护 WCF

本文关键字:证书 保护 WCF BinarySecurityToken 通过 使用 | 更新日期: 2023-09-27 18:30:36

我不是 WCF 专家,我只知道服务安全的基础知识,所以也许我要指出的大多数事情都是错误的。也就是说,我需要调用一个需要 SOAP 标头特定格式的 3d 参与方服务。它们要求 soap 标头提供:1) 时间戳块2) 二进制代币3)摘要(要加密的部分数据的校验和)

他们为我提供了这个请求示例(我已经删除了合理的部分)

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"
                                wsu:Id="...omissis...">
      </wsse:BinarySecurityToken>
      <ds:Signature Id="SIG-6" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces PrefixList="S" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#TS-5">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="wsse S" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>...omissis...</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
          ....
          ...omissis...
          ....
        </ds:SignatureValue>
        <ds:KeyInfo Id="KI-...omissis...">
          <wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="STR-...omissis..." xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd">
            <wsse:Reference URI="#X509-...omissis..." ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      <wsu:Timestamp wsu:Id="TS-5">
        <wsu:Created>2013-03-27T15:10:18.523Z</wsu:Created>
        <wsu:Expires>2013-03-27T15:26:58.523Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </S:Header>
<S:Body>
    ...clear (not encrypted) body of the soap request
</S:Body>
</S:Envelope>

他们还给了我一个WSDL和一个xsd。我所做的是创建一个新的 Web 应用程序,使用 wsdl 作为服务参考。检查web.config,我可以看到这已经创建了一个基本的HttpBinding,如下所示

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="CPBinding">
          <security mode="Transport" />
        </binding>
        <binding name="CPBinding1" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://...omissis"
        binding="basicHttpBinding" bindingConfiguration="CPBinding"
        contract="BTClient.CPCUVPortType" name="CPCUVPort" />
    </client>
  </system.serviceModel>

但是此绑定不使用任何类型的安全策略,因此我创建了一个考虑证书(对于相互证书)的行为,如下所示

 <behaviors>
      <endpointBehaviors>
        <behavior name="CustomBehaviorForCertificates">
          <clientCredentials>
            <clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" findValue="...omissis..." />
            <serviceCertificate>
              <scopedCertificates>
                <add targetUri="https://...omissis..." storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindByThumbprint" findValue="...omissis..." />
              </scopedCertificates>
              <authentication certificateValidationMode="PeerTrust" revocationMode="NoCheck" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

并在绑定中引用了它。通过检查传出消息(使用自定义检查器的 BeforeSendRequest 方法),我可以看到它完全忽略了证书,发送与没有行为的证书相同的请求。3d 派对服务对我的请求的回答如下:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsu:Timestamp wsu:Id="Timestamp-..." xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsu:Created>2013-09-06T14:31:28Z</wsu:Created>
        <wsu:Expires>2013-09-06T14:36:28Z</wsu:Expires>
      </wsu:Timestamp>
      <wsse:BinarySecurityToken wsu:Id="SecurityToken-...." EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        ...omissis...
      </wsse:BinarySecurityToken>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
          <Reference URI="#Timestamp-...">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <DigestValue>...omissis...</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>...omissis...</SignatureValue>
            <KeyInfo>
                <wsse:SecurityTokenReference xmlns="">
                    <wsse:Reference URI="#SecurityToken-...omissis..." ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
                </wsse:SecurityTokenReference>
            </KeyInfo>
        </Signature>
    </wsse:Security>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body wsu:Id="..." xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <SOAP-ENV:Fault>
      <faultcode>wsse:FailedCheck</faultcode>
      <faultstring>The signature or decryption was invalid</faultstring>
      <detail>
        <e:myfaultdetails xmlns:e="Some-URI">
          <errorCode>500</errorCode>
          <message>INTERNAL_SERVER_ERROR</message>
        </e:myfaultdetails>
      </detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

在做了一些研究之后,我已经读到,为了提供BinarySecurityToken,我需要实现一个customBinding。我尝试了不同的方法和组合,但我总是无法取得进展。

例如,通过使用此自定义行为:

  <customBinding>
    <binding name="cb">
      <security authenticationMode="MutualCertificateDuplex" requireDerivedKeys="false" includeTimestamp="true"
        messageProtectionOrder="EncryptBeforeSign" messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10" />
      <textMessageEncoding messageVersion="Soap11" />
      <httpsTransport />
    </binding>
  </customBinding>

我收到如下内部服务器错误:

ExceptionType: System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.InnerException: System.ServiceModel.FaultException:Internal Error

而且,最重要的是...我的传出请求总是与基本的HTTP绑定请求相同!显然我不太明白一些事情。我可以看到,使用 basicHttpBindig 我可以正确地与他们通信,但我无法提供所需的安全片段。如果我尝试使用任何其他绑定之王(例如 wsHttpBinding 或自定义绑定),我会收到一条错误消息。有人可以帮助我了解完成此类工作的正确方法吗?任何帮助将不胜感激。

多谢。

编辑:

我正在添加传出请求:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <ActivityId CorrelationId="dd479557-7e51-41de-822b-d2ac669ff827" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">bbd2f92b-33d5-4ec0-87b6-690f2142cdf5</ActivityId>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="uuid-7b22e181-f551-4821-91e0-cf8c9b8d9eef-1">
        <u:Created>2013-09-09T12:24:03.563Z</u:Created>
        <u:Expires>2013-09-09T12:29:03.563Z</u:Expires>
      </u:Timestamp>
      <o:BinarySecurityToken>
        <!-- Removed-->
      </o:BinarySecurityToken>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
          <Reference URI="#_1">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>...omissis...</DigestValue>
          </Reference>
          <Reference URI="#uuid-7b22e181-f551-4821-91e0-cf8c9b8d9eef-1">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>...omissis...=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>...omissis...</SignatureValue>
        <KeyInfo>
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-e31a3eed-6ac7-4dcb-bfb2-2384764acd93-2"></o:Reference>
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <CPCUValidityRequest xmlns="http://......omissis...">
      <serviceType>3</serviceType>
      <arg1>arg1</arg1>
      <arg2>arg2</arg2>
      ...omissis...
    </CPCUValidityRequest>
  </s:Body>
</s:Envelope>

解决方案:实际上,由于错误,我无法成功调用远程服务(如已接受解决方案的注释中所述。但我可以说这个问题得到了回答,因为我设法创建了一个与所需请求大致相似的请求。非常感谢亚龙。

附注:(对于那些会遇到类似问题的人的提示,要检查传出/传入请求,请尝试使用 Microsoft 跟踪查看器,按照本答案 https://stackoverflow.com/a/11678740/2274007 中的建议启用跟踪(请记住也遵循评论中的建议))

使用 BinarySecurityToken 通过 X.509 证书保护 WCF

请发布您的传出请求。在您的绑定中,我会更改为身份验证模式="互助证书"。否则它看起来不错。

此外,为了发送仅签名的消息而不是加密的消息,请在数据合约之上添加此属性(参考.cs):

[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.SimpleServiceSoap", ProtectionLevel=System.Net.Security.ProtectionLevel.Sign)]

有关此方法的更多详细信息,请参阅此 WCF 安全提示文章。

试试这个 customBinding:

 <customBinding>
    <binding name="cb">
      <security authenticationMode="MutualCertificateDuplex" 
                defaultAlgorithmSuite="Basic128Rsa15" 
                requireDerivedKeys="false"
                enableUnsecuredResponse="true"
                messageProtectionOrder="EncryptBeforeSign" 
                messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
      </security>
      <textMessageEncoding messageVersion="Soap11WSAddressing10"/>
    <httpsTransport />
    </binding>
  </customBinding>