WCF Web 服务请求:在 SecurityTokenReference 中添加 Reference 标记而不是 KeyIdentifier 标记
WCF Webservice request : Add a Reference tag instead of KeyIdentifier tag in SecurityTokenReference
我需要通过 .NET 使用 Java 网络服务。请求必须签名,并且证书需要包含在请求中。
当使用下面的 'GetClient' 方法时,除了一个字段外,请求是正确的。
在 SecurityTokenReference 元素中,添加了 'KeyIdentifier'。
此 SecurityTokenReference 字段应包含指向 'SignedInfo' 元素中第三个引用的 'Reference' 字段:
</o:Security>
</s:Header>
<o:BinarySecurityToken>...</o:BinarySecurityToken>
<Signature>
<SignedInfo>
<CanonicalizationMethod></CanonicalizationMethod>
<SignatureMethod></SignatureMethod>
<Reference URI="#_1">...</Reference>
<Reference URI="#uuid-001">...</Reference>
<Reference URI="#uuid-002">...</Reference>
</SignedInfo>
<SignatureValue>...</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:KeyIdentifier >...</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
所以
<o:SecurityTokenReference>
<o:KeyIdentifier >...</o:KeyIdentifier>
</o:SecurityTokenReference>
应该是
<o:SecurityTokenReference>
<o:Reference ValueType="..." URI="uuid-002" />
</o:SecurityTokenReference>
但是我不能让它工作。
使用时
InitiatorTokenParameters InclusionMode = SecurityTokenInclusionMode.Once
添加了正确的'Reference'标签,但是随后生成了双'BinarySecurityToken'标签,导致webservice被拒绝。
有解决办法吗?
public wsClient GetClient()
{
CustomBinding b = new CustomBinding();
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
AsymmetricSecurityBindingElement asec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
asec.SetKeyDerivation(false);
asec.AllowInsecureTransport = true;
asec.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
asec.IncludeTimestamp = true;
asec.ProtectTokens = true;
asec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
asec.InitiatorTokenParameters = new X509SecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.Never, //.Once, ----> Once creates correct SecurityTokenReference, but double BinarySecurityToken
ReferenceStyle = SecurityTokenReferenceStyle.Internal
};
asec.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
b.Elements.Add(asec);
b.Elements.Add(textMessageEncoding);
b.Elements.Add(transport);
string url = "https://service";
var c = new wsClient(b, new EndpointAddress(new Uri(url),
new DnsEndpointIdentity(kgParams.DnsEndpointIdentity), new AddressHeaderCollection()));
X509Certificate cert = GetCertificate();
c.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(cert);
c.ClientCredentials.ServiceCertificate.DefaultCertificate = c.ClientCredentials.ClientCertificate.Certificate;
c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
return c;
}
在为这个问题苦苦挣扎了几天之后,尽管赏金为 250 分,但没有对 SO 发表任何评论或回答,我只能得出结论,这是 Java 和 .NET 之间的不兼容性WCF。
最后我无奈地放弃了WCF,从头开始重新创建了整个*****请求。
这意味着:
- 创建包含所需数据的 XmlDocument
- 将证书作为 Base64 添加到 header
- 手动为请求添加时间戳
- 手动添加正确 KeyInfo 标签
- 使用适当的 GUID 手动添加所有引用
- 使用 SignedXml 和证书手动签署所有元素
- 手动post请求
服务器毫无异议地接受了请求。
我需要通过 .NET 使用 Java 网络服务。请求必须签名,并且证书需要包含在请求中。
当使用下面的 'GetClient' 方法时,除了一个字段外,请求是正确的。 在 SecurityTokenReference 元素中,添加了 'KeyIdentifier'。 此 SecurityTokenReference 字段应包含指向 'SignedInfo' 元素中第三个引用的 'Reference' 字段:
</o:Security>
</s:Header>
<o:BinarySecurityToken>...</o:BinarySecurityToken>
<Signature>
<SignedInfo>
<CanonicalizationMethod></CanonicalizationMethod>
<SignatureMethod></SignatureMethod>
<Reference URI="#_1">...</Reference>
<Reference URI="#uuid-001">...</Reference>
<Reference URI="#uuid-002">...</Reference>
</SignedInfo>
<SignatureValue>...</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:KeyIdentifier >...</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
所以
<o:SecurityTokenReference>
<o:KeyIdentifier >...</o:KeyIdentifier>
</o:SecurityTokenReference>
应该是
<o:SecurityTokenReference>
<o:Reference ValueType="..." URI="uuid-002" />
</o:SecurityTokenReference>
但是我不能让它工作。
使用时
InitiatorTokenParameters InclusionMode = SecurityTokenInclusionMode.Once
添加了正确的'Reference'标签,但是随后生成了双'BinarySecurityToken'标签,导致webservice被拒绝。 有解决办法吗?
public wsClient GetClient()
{
CustomBinding b = new CustomBinding();
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
AsymmetricSecurityBindingElement asec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
asec.SetKeyDerivation(false);
asec.AllowInsecureTransport = true;
asec.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
asec.IncludeTimestamp = true;
asec.ProtectTokens = true;
asec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
asec.InitiatorTokenParameters = new X509SecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.Never, //.Once, ----> Once creates correct SecurityTokenReference, but double BinarySecurityToken
ReferenceStyle = SecurityTokenReferenceStyle.Internal
};
asec.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
b.Elements.Add(asec);
b.Elements.Add(textMessageEncoding);
b.Elements.Add(transport);
string url = "https://service";
var c = new wsClient(b, new EndpointAddress(new Uri(url),
new DnsEndpointIdentity(kgParams.DnsEndpointIdentity), new AddressHeaderCollection()));
X509Certificate cert = GetCertificate();
c.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(cert);
c.ClientCredentials.ServiceCertificate.DefaultCertificate = c.ClientCredentials.ClientCertificate.Certificate;
c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
return c;
}
在为这个问题苦苦挣扎了几天之后,尽管赏金为 250 分,但没有对 SO 发表任何评论或回答,我只能得出结论,这是 Java 和 .NET 之间的不兼容性WCF。
最后我无奈地放弃了WCF,从头开始重新创建了整个*****请求。 这意味着:
- 创建包含所需数据的 XmlDocument
- 将证书作为 Base64 添加到 header
- 手动为请求添加时间戳
- 手动添加正确 KeyInfo 标签
- 使用适当的 GUID 手动添加所有引用
- 使用 SignedXml 和证书手动签署所有元素
- 手动post请求
服务器毫无异议地接受了请求。