【问题标题】:Secure WCF via X.509 certificate with BinarySecurityToken通过带有 BinarySecurityToken 的 X.509 证书保护 WCF
【发布时间】:2013-09-06 14:59:28
【问题描述】:

我不是 WCF 专家,我只知道服务安全的基础知识,所以我要指出的大部分内容可能都是错误的。 也就是说,我需要调用 3d 方服务,该服务需要 SOAP 标头的特定格式。 他们要求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,我可以看到这已经创建了一个这样的 basicHttpBinding

<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

而且,最重要的是...我的传出请求始终与 basicHttpBinding 相同! 显然我还没有很好地理解一些东西。我可以看到,使用 basicHttpBindig 我可以与他们正确通信,但我无法提供所需的安全片段。如果我尝试使用任何其他绑定之王(例如 wsHttpBinding 或 customBinding),我会收到一条错误消息。 有人可以帮我理解做这项工作的正确方法吗?任何帮助将不胜感激。

非常感谢。

编辑:

我正在添加传出请求:

<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>

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

PS:( 对那些有类似问题的人的提示,要检查传出/传入请求,请尝试使用 Microsoft Trace Viewer,按照此答案https://stackoverflow.com/a/11678740/2274007 中的建议启用跟踪(请记住也遵循建议在评论中))

【问题讨论】:

  • 您能发布您最终的 app.config 更改吗?

标签: c# wcf web-services soap wcf-security


【解决方案1】:

请发布您的传出请求。 在您的绑定中,我将更改为 authenticationMode="mutualCertificate"。否则看起来不错。

此外,为了发送刚刚签名的消息而不是加密的消息,请在您的数据合同 (reference.cs) 顶部添加此属性:

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

wcf security tips 文章中有关此方法的更多详细信息。

【讨论】:

  • 感谢您的回答,我已经更新了问题。我会尝试修复并尽快通知您。
  • 我正在阅读您的博文……真是太棒了。现在我终于可以理解一些东西了......谢谢=)
  • 您发出的请求没有安全性。一种选择是,在获取请求之前,您从 wcf 日志中的错误位置对请求进行工具处理。使用 Fiddler 或从 log 的传输阶段获取。另一种选择是您的绑定配置未应用于端点,可能是配置错误
  • 我已经删除了我之前的评论,因为我已经成功地读取了安全的传出请求。我正在尝试分析差异以尝试了解如何自己解决它(您已经帮助了我很多,非常感谢)。同时,我将使用正确的传出请求更新我的问题,以帮助处于相同情况的其他人。
  • 可能很难。可以尝试以某种方式使用此示例 webservices20.blogspot.co.il/2009/02/… 并从 OutgoingSignatureParts 中删除 Body 部分
【解决方案2】:

试试这个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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多