我正在尝试从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.InclusionMode
在InitiatorTokenParameters
, RecipientTokenParameters
或EndpointSupportingTokenParameters.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">
我用客户机消息检查器解决了这个问题,我在签名和发送名称空间之前调整它们。