在到 WCF Web 服务的 SOAP 消息中,如何将 KeyIdentifier 直接放在 SecurityTokenReference 中(内联,不使用引用令牌)
Posted
技术标签:
【中文标题】在到 WCF Web 服务的 SOAP 消息中,如何将 KeyIdentifier 直接放在 SecurityTokenReference 中(内联,不使用引用令牌)【英文标题】:In SOAP message to WCF web service, how to put KeyIdentifier directly inside SecurityTokenReference (inline, without using Reference token) 【发布时间】:2016-04-11 21:00:42 【问题描述】:我成功地通过 SoapUI 与 WCF 服务通信(我获得了有关如何配置它的规范),但是我在将这些设置复制到 .NET 应用程序时遇到了麻烦。结果表明生成的 SOAP 消息的形状(通过 Fiddler 窥视)被 Web 服务拒绝,该服务期望更严格的信封布局。
我非常接近。在这张照片上……
...您可以看到三个 SOAP 消息:
1. 将X509SecurityTokenParameters.InclusionMode
设置为AlwaysToRecipient
2. 将X509SecurityTokenParameters.InclusionMode
设置为Never
3. 预期的安全令牌,在 SoapUI 上测试。
如何使用 C# 代码从第 3 点实现信封? 我没有使用 app.config
文件,整个配置都在 C# 代码中(但我并不致力于保持这种方式, 就这样发生了)。当前代码:
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Text;
public class CustomAlgorithmSuite : SecurityAlgorithmSuite
public override string DefaultAsymmetricKeyWrapAlgorithm get return "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
public override string DefaultAsymmetricSignatureAlgorithm get return "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
public override string DefaultCanonicalizationAlgorithm get return "http://www.w3.org/2001/10/xml-exc-c14n#";
public override string DefaultDigestAlgorithm get return "http://www.w3.org/2000/09/xmldsig#sha1";
public override string DefaultEncryptionAlgorithm get return "http://www.w3.org/2001/04/xmlenc#aes256-cbc";
public override int DefaultEncryptionKeyDerivationLength get return SecurityAlgorithmSuite.Default.DefaultEncryptionKeyDerivationLength;
public override int DefaultSignatureKeyDerivationLength get return SecurityAlgorithmSuite.Default.DefaultSignatureKeyDerivationLength;
public override int DefaultSymmetricKeyLength get return SecurityAlgorithmSuite.Default.DefaultSymmetricKeyLength;
public override string DefaultSymmetricKeyWrapAlgorithm get return "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
public override string DefaultSymmetricSignatureAlgorithm get return "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
public override bool IsAsymmetricKeyLengthSupported(int length) return true;
public override bool IsSymmetricKeyLengthSupported(int length) return true;
class Program
static void Main()
X509SecurityTokenParameters x509Params = new X509SecurityTokenParameters()
X509ReferenceStyle = X509KeyIdentifierClauseType.RawDataKeyIdentifier,
InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient,
ReferenceStyle = SecurityTokenReferenceStyle.External,
RequireDerivedKeys = false
;
SecurityBindingElement security = new TransportSecurityBindingElement()
MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10,
DefaultAlgorithmSuite = new CustomAlgorithmSuite()
;
security.EndpointSupportingTokenParameters.Endorsing.Add(x509Params);
security.SetKeyDerivation(false);
//security.IncludeTimestamp = false;
TextMessageEncodingBindingElement encoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
//transport.RequireClientCertificate = true;
CustomBinding customBinding = new CustomBinding(security, encoding, transport);
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
var twoCertificatesInOneFile = new X509Certificate2Collection();
twoCertificatesInOneFile.Import("foo path", "foo cert pass", X509KeyStorageFlags.Exportable);
someGeneratedServiceClass client = new someGeneratedServiceClass(customBinding, new EndpointAddress(new Uri("foo webservice address"), EndpointIdentity.CreateDnsIdentity(twoCertificatesInOneFile[0].FriendlyName)));
client.ClientCredentials.ServiceCertificate.DefaultCertificate = twoCertificatesInOneFile[0];
client.ClientCredentials.ClientCertificate.Certificate = twoCertificatesInOneFile[1];
//client.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.None;
client.ClientCredentials.UserName.UserName = "foo user";
client.ClientCredentials.UserName.Password = "foo pass";
client.someServiceCall("foo", "foo", false, out i1, out i2);
【问题讨论】:
【参考方案1】:我最终使用了InclusionMode = SecurityTokenInclusionMode.Never
,然后劫持了消息并手动替换了错误的标签。
public class CustomProxy_portClient : GeneratedProxy_portClient
public CustomProxy_portClient() : base()
Endpoint.Behaviors.Remove(typeof(ClientCredentials));
Endpoint.Behaviors.Add(new CustomClientCredentials());
class CustomClientCredentials : ClientCredentials
public CustomClientCredentials() : base()
public CustomClientCredentials(ClientCredentials ClientCredentials) : base(ClientCredentials)
public override SecurityTokenManager CreateSecurityTokenManager()
return new CustomSecurityTokenManager(this);
protected override ClientCredentials CloneCore()
return new CustomClientCredentials(this);
class CustomSecurityTokenManager : ClientCredentialsSecurityTokenManager
public CustomSecurityTokenManager(ClientCredentials clientCredentials) : base(clientCredentials)
public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
return new CustomWSSecurityTokenSerializer();
class CustomWSSecurityTokenSerializer : WSSecurityTokenSerializer
protected override void WriteKeyIdentifierClauseCore(XmlWriter writer, SecurityKeyIdentifierClause keyIdentifierClause)
string xml;
using(MemoryStream ms = new MemoryStream())
XmlTextWriter tempWriter = new XmlTextWriter(ms, new UTF8Encoding(false));
base.WriteKeyIdentifierClauseCore(tempWriter, keyIdentifierClause);
xml = Encoding.UTF8.GetString(ms.ToArray());
XmlDocument originalKeyIdentifierClause = new XmlDocument();
originalKeyIdentifierClause.LoadXml(xml);
writer.WriteStartElement("SecurityTokenReference");
writer.WriteElementString("KeyIdentifier", originalKeyIdentifierClause.InnerText);
writer.WriteEndElement();
【讨论】:
以上是关于在到 WCF Web 服务的 SOAP 消息中,如何将 KeyIdentifier 直接放在 SecurityTokenReference 中(内联,不使用引用令牌)的主要内容,如果未能解决你的问题,请参考以下文章