Web services 在到WCF web服务的SOAP消息中,如何将KeyIdentifier直接放在SecurityTokenReference内(内联,不使用引用令牌)
我成功地通过SoapUI与WCF服务通信(我得到了关于如何配置它的规范),但在将这些设置复制到.NET应用程序时遇到了麻烦。原来生成的SOAP消息的形状(通过Fiddler偷看)被web服务拒绝,web服务希望信封的布局更严格 我很接近。在这张照片上 。。。您可以看到三条SOAP消息: 1.带有Web services 在到WCF web服务的SOAP消息中,如何将KeyIdentifier直接放在SecurityTokenReference内(内联,不使用引用令牌),web-services,wcf,soap,app-config,ws-security,Web Services,Wcf,Soap,App Config,Ws Security,我成功地通过SoapUI与WCF服务通信(我得到了关于如何配置它的规范),但在将这些设置复制到.NET应用程序时遇到了麻烦。原来生成的SOAP消息的形状(通过Fiddler偷看)被web服务拒绝,web服务希望信封的布局更严格 我很接近。在这张照片上 。。。您可以看到三条SOAP消息: 1.带有X509SecurityTokenParameters.InclusionMode设置为AlwayStoreCippent 2.使用X509SecurityTokenParameters.Inclusi
X509SecurityTokenParameters.InclusionMode
设置为AlwayStoreCippent
2.使用X509SecurityTokenParameters.InclusionMode
设置为从不
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);
}
}
我最终使用了
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();
}
}
我最终使用了
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();
}
}