签名SOAP报头有两个binarysecuritytoken(实际上它可以而且应该有一个)



我正在尝试从STS服务请求安全令牌。这个服务是第三方的,所以我不能修改它,检查日志等。

生成的请求SOAP消息看起来几乎与我的示例请求相同。只是添加了两个具有相同值的BinarySecurityToken元素,而正确的请求仅包含一个令牌。

SOAP消息看起来像这样:

<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>
    <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-4db59a59-9180-4efe-92d0-14aefcbf68d5-1">
        <u:Created>2014-08-22T07:51:45.763Z</u:Created>
        <u:Expires>2014-08-22T08:51:45.763Z</u:Expires>
      </u:Timestamp>
      <o:BinarySecurityToken u:Id="uuid-54e35db8-29dc-4d3c-bba2-c6eacb7cf4e9-4" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">...</o:BinarySecurityToken>
      <o:BinarySecurityToken u:Id="uuid-54e35db8-29dc-4d3c-bba2-c6eacb7cf4e9-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">...</o: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="#_1">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>...</DigestValue>
          </Reference>
          <Reference URI="#uuid-4db59a59-9180-4efe-92d0-14aefcbf68d5-1">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>...</DigestValue>
          </Reference>
          <Reference URI="#uuid-54e35db8-29dc-4d3c-bba2-c6eacb7cf4e9-2">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>...</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>.../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-54e35db8-29dc-4d3c-bba2-c6eacb7cf4e9-4"/>
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_1">
    <trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
      <trust:Claims Dialect="http://docs.oasis-open.org/wsfed/authorization/200706/authclaims" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706">
        <auth:ClaimType Uri="custom claim" Optional="true">
          <auth:Value>...</auth:Value>
        </auth:ClaimType>
      </trust:Claims>
      <trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey</trust:KeyType>
      <trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
      <trust:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</trust:TokenType>
    </trust:RequestSecurityToken>
  </s:Body>
</s:Envelope>

安全绑定元素和绑定是这样配置的:

AsymmetricSecurityBindingElement messageSecurity = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(
    MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
);
messageSecurity.IncludeTimestamp = true;
messageSecurity.LocalClientSettings.TimestampValidityDuration = TimeSpan.FromHours(1);
messageSecurity.ProtectTokens = true;
messageSecurity.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
messageSecurity.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
messageSecurity.EnableUnsecuredResponse = true;
X509SecurityTokenParameters initiatorParams = new X509SecurityTokenParameters
{
    InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient,
    ReferenceStyle = SecurityTokenReferenceStyle.Internal,
    RequireDerivedKeys = false,
    X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial
};
X509SecurityTokenParameters recipientParams = new X509SecurityTokenParameters
{
    InclusionMode = SecurityTokenInclusionMode.Never,
    ReferenceStyle = SecurityTokenReferenceStyle.Internal,
    RequireDerivedKeys = false,
    X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial
};
X509SecurityTokenParameters endpointParams = new X509SecurityTokenParameters
{
    InclusionMode = SecurityTokenInclusionMode.Once,
    ReferenceStyle = SecurityTokenReferenceStyle.Internal,
    RequireDerivedKeys = false,
    X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial
};
messageSecurity.InitiatorTokenParameters = initiatorParams;
messageSecurity.RecipientTokenParameters = recipientParams;
messageSecurity.EndpointSupportingTokenParameters.Signed.Add(endpointParams);
HttpsTransportBindingElement elem = new HttpsTransportBindingElement();
CustomBinding binding = new CustomBinding(messageSecurity, new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8), elem);
return binding;

我还专门将WSTrustChannelFactory配置为仅对消息签名(不签名&加密):

var factory = new WSTrustChannelFactory(binding, endpoint);
factory.Endpoint.Contract.ProtectionLevel = ProtectionLevel.Sign;

唯一的问题是服务的安全策略提到启动令牌应该是SAML令牌,而我使用的是X509SecurityTokenParameters。这主要是因为我不知道如何添加SAML令牌,但我不确定这会有什么不同。

作为参考,WS-Security策略是:
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> 
        <sp:AsymmetricBinding>
        <wsp:Policy> 
            <sp:InitiatorToken>
                <wsp:Policy>
                    <sp:SamlToken
                    sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> 
                        <wsp:Policy>
                            <sp:WssSamlV11Token10/>
                        </wsp:Policy>
                    </sp:SamlToken>
                </wsp:Policy>
            </sp:InitiatorToken>
        <sp:RecipientToken>
            <wsp:Policy>
                <sp:X509Token
                sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
            <wsp:Policy>
                <sp:WssX509V3Token10/>
            </wsp:Policy>
                </sp:X509Token>
            </wsp:Policy>
        </sp:RecipientToken>
        <sp:AlgorithmSuite>
            <wsp:Policy>
                <sp:Basic256/>
            </wsp:Policy>
        </sp:AlgorithmSuite>
        <sp:Layout>
            <wsp:Policy>
                <sp:Lax/>
            </wsp:Policy>
        </sp:Layout>
        <sp:IncludeTimestamp/>
        <sp:ProtectTokens/>
        <sp:OnlySignEntireHeadersAndBody/>
        </wsp:Policy>
    </sp:AsymmetricBinding>
    <sp:Wss10>
        <wsp:Policy>
            <sp:MustSupportRefKeyIdentifier/>
            <sp:MustSupportRefIssuerSerial/>
        </wsp:Policy>
    </sp:Wss10>
    <sp:SignedParts>
        <sp:Body/>
    </sp:SignedParts>
</wsp:Policy>

最终,我想找到一种方法让消息只包含一个二进制令牌。如果唯一的方法是在发送SOAP XML之前手动修改它,那么就这样吧。

通过使用以下代码创建绑定,我已经成功地从STS服务获得了令牌。

X509SecurityTokenParameters.InclusionModeInitiatorTokenParameters, RecipientTokenParametersEndpointSupportingTokenParameters.Signed上被设置为SecurityTokenInclusionMode.Never以外的任何东西时,似乎添加了额外的令牌。

创建绑定的代码如下,以防有人需要它:

var messageSecurity = new AsymmetricSecurityBindingElement
{
    MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10,
    InitiatorTokenParameters = new X509SecurityTokenParameters
    {
        InclusionMode = SecurityTokenInclusionMode.Never,
        ReferenceStyle = SecurityTokenReferenceStyle.Internal,
    },
    RecipientTokenParameters = new X509SecurityTokenParameters
    {
        InclusionMode = SecurityTokenInclusionMode.Never,
        ReferenceStyle = SecurityTokenReferenceStyle.Internal
    },
    MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt,
    SecurityHeaderLayout = SecurityHeaderLayout.Lax,
    EnableUnsecuredResponse = true,
    IncludeTimestamp = true
};
messageSecurity.SetKeyDerivation(false);
messageSecurity.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
messageSecurity.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
messageSecurity.LocalClientSettings.TimestampValidityDuration = TimeSpan.FromHours(1);
messageSecurity.RequireSignatureConfirmation = true;
messageSecurity.AllowSerializedSigningTokenOnReply = true;
HttpsTransportBindingElement elem = new HttpsTransportBindingElement { RequireClientCertificate = true };
CustomBinding binding = new CustomBinding(messageSecurity, new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8), elem);

我还遇到了SOAP主体中RequestSecurityToken序列化的问题。WCF在这里使用了不同的名称空间:

<auth:ClaimType Uri="..." xmlns:auth="http://schemas.xmlsoap.org/ws/2006/12/authorization">

我用客户机消息检查器解决了这个问题,我在签名和发送名称空间之前调整它们。

相关内容

最新更新