1

WCF を使用して従来の Web サービスを使用する際に問題が発生しています。Web サービスが異なる署名キーと暗号化キーを使用していたという事実を扱っていた 1 つの問題を解決しました。しかし、Web サービス呼び出しを行うと、バージョン ミスマッチの応答が返されます。WSE で生成されたエンベロープを見ると、SOAP のバージョンが WCF で生成されたものと異なることに気付きました。

私の WSE エンベロープ ヘッダーは次のようになります。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

一方、WCF エンベロープ ヘッダーは

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">

soap エンベロープの名前空間とプレフィックスを変更するためのコードをいくつか追加しました。

        EndpointAddress serviceEndpoint = 
            new EndpointAddress(new Uri("http://mylegacywebservice.com"));
        CustomBinding binding = new CustomBinding();
        AsymmetricSecurityBindingElement securityBE = 
        SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(
                MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
        // Add a custom IdentityVerifier because the service uses two certificates 
        // (one for signing and one for encryption) and an endpoint identity that 
        // contains a single identity claim.
        securityBE.LocalClientSettings.IdentityVerifier = new MyIdentityVerifier();
        binding.Elements.Add(securityBE);
        CompositeDuplexBindingElement compositeDuplex = 
        new CompositeDuplexBindingElement();
        compositeDuplex.ClientBaseAddress = new Uri("http://mylegacywebservice.com");
        binding.Elements.Add(compositeDuplex);

        binding.Elements.Add(new OneWayBindingElement());

        binding.Elements.Add(new  HttpTransportBindingElement());
          Dictionary<string, string> namespaceToPrefixMapping = new Dictionary<string, string> 
{ 
    { "http://schemas.xmlsoap.org/soap/envelope/", "soap" }, 
    { "http://schemas.xmlsoap.org/ws/2004/08/addressing", "wsa" }, 
}; 
  binding = ReplacePrefixMessageEncodingBindingElement.ReplaceEncodingBindingElement( 
    new WSHttpBinding(SecurityMode.None), 
    namespaceToPrefixMapping); 

以下は、prefixreplace.cs です。

public class PrefixReplacer 
  { 
    const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/"; 
    Dictionary<string, string> namespaceToNewPrefixMapping = new Dictionary<string, string>(); 


public void AddNamespace(string namespaceUri, string newPrefix) 
{ 
    this.namespaceToNewPrefixMapping.Add(namespaceUri, newPrefix); 
} 

public void ChangePrefixes(XmlDocument doc) 
{ 
    XmlElement element = doc.DocumentElement; 
    XmlElement newElement = ChangePrefixes(doc, element); 
    doc.LoadXml(newElement.OuterXml); 
} 

private XmlElement ChangePrefixes(XmlDocument doc, XmlElement element) 
{ 
    string newPrefix; 
    if (this.namespaceToNewPrefixMapping.TryGetValue(element.NamespaceURI, out newPrefix)) 
    { 
        XmlElement newElement = doc.CreateElement(newPrefix, element.LocalName, element.NamespaceURI); 
        List<XmlNode> children = new List<XmlNode>(element.ChildNodes.Cast<XmlNode>()); 
        List<XmlAttribute> attributes = new List<XmlAttribute>(element.Attributes.Cast<XmlAttribute>()); 
        foreach (XmlNode child in children) 
        { 
            newElement.AppendChild(child); 
        } 

        foreach (XmlAttribute attr in attributes) 
        { 
            newElement.Attributes.Append(attr); 
        } 

        element = newElement; 
    } 

    List<XmlAttribute> newAttributes = new List<XmlAttribute>(); 
    bool modified = false; 
    for (int i = 0; i < element.Attributes.Count; i++) 
    { 
        XmlAttribute attr = element.Attributes[i]; 
        if (this.namespaceToNewPrefixMapping.TryGetValue(attr.NamespaceURI, out newPrefix)) 
        { 
            XmlAttribute newAttr = doc.CreateAttribute(newPrefix, attr.LocalName, attr.NamespaceURI); 
            newAttr.Value = attr.Value; 
            newAttributes.Add(newAttr); 
            modified = true; 
        } 
        else if (attr.NamespaceURI == XmlnsNamespace && this.namespaceToNewPrefixMapping.TryGetValue(attr.Value, out newPrefix)) 
        { 
            XmlAttribute newAttr; 
            if (newPrefix != "") 
            { 
                newAttr = doc.CreateAttribute("xmlns", newPrefix, XmlnsNamespace); 
            } 
            else 
            { 
                newAttr = doc.CreateAttribute("xmlns"); 
            } 

            newAttr.Value = attr.Value; 
            newAttributes.Add(newAttr); 
            modified = true; 
        } 
        else 
        { 
            newAttributes.Add(attr); 
        } 
    } 

    if (modified) 
    { 
        element.Attributes.RemoveAll(); 
        foreach (var attr in newAttributes) 
        { 
            element.Attributes.Append(attr); 
        } 
    } 

    List<KeyValuePair<XmlNode, XmlNode>> toReplace = new List<KeyValuePair<XmlNode, XmlNode>>(); 
    foreach (XmlNode child in element.ChildNodes) 
    { 
        XmlElement childElement = child as XmlElement; 
        if (childElement != null) 
        { 
            XmlElement newChildElement = ChangePrefixes(doc, childElement); 
            if (newChildElement != childElement) 
            { 
                toReplace.Add(new KeyValuePair<XmlNode, XmlNode>(childElement, newChildElement)); 
            } 
        } 
    } 

    if (toReplace.Count > 0) 
    { 
        for (int i = 0; i < toReplace.Count; i++) 
        { 
            element.InsertAfter(toReplace[i].Value, toReplace[i].Key); 
            element.RemoveChild(toReplace[i].Key); 
        } 
    } 

    return element; 
} 

}

以下は、ReplacePrefixMessageEncodingBindingElement です。

public class ReplacePrefixMessageEncodingBindingElement : MessageEncodingBindingElement 
{ 
    MessageEncodingBindingElement inner; 
    Dictionary<string, string> namespaceToPrefixMapping = new Dictionary<string, string>(); 
public ReplacePrefixMessageEncodingBindingElement(MessageEncodingBindingElement inner) 
{ 
    this.inner = inner; 
} 

private ReplacePrefixMessageEncodingBindingElement(ReplacePrefixMessageEncodingBindingElement other) 
{ 
    this.inner = other.inner; 
    this.namespaceToPrefixMapping = new Dictionary<string, string>(other.namespaceToPrefixMapping); 
} 

public void AddNamespaceMapping(string namespaceUri, string newPrefix) 
{ 
    this.namespaceToPrefixMapping.Add(namespaceUri, newPrefix); 
} 

public override MessageEncoderFactory CreateMessageEncoderFactory() 
{ 
    return new ReplacePrefixMessageEncoderFactory(this.inner.CreateMessageEncoderFactory(), this.namespaceToPrefixMapping); 
} 

public override MessageVersion MessageVersion 
{ 
    get { return this.inner.MessageVersion; } 
    set { this.inner.MessageVersion = value; } 
} 

public override BindingElement Clone() 
{ 
    return new ReplacePrefixMessageEncodingBindingElement(this); 
} 

public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) 
{ 
    context.BindingParameters.Add(this); 
    return context.BuildInnerChannelListener<TChannel>(); 
} 

public override bool CanBuildChannelListener<TChannel>(BindingContext context) 
{ 
    return context.CanBuildInnerChannelListener<TChannel>(); 
} 

public static CustomBinding ReplaceEncodingBindingElement(Binding originalBinding, Dictionary<string, string> namespaceToPrefixMapping) 
{ 
    CustomBinding custom = originalBinding as CustomBinding; 
    if (custom == null) 
    { 
        custom = new CustomBinding(originalBinding); 
    } 

    for (int i = 0; i < custom.Elements.Count; i++) 
    { 
        if (custom.Elements[i] is MessageEncodingBindingElement) 
        { 
            ReplacePrefixMessageEncodingBindingElement element = new ReplacePrefixMessageEncodingBindingElement((MessageEncodingBindingElement)custom.Elements[i]); 
            foreach (var mapping in namespaceToPrefixMapping) 
            { 
                element.AddNamespaceMapping(mapping.Key, mapping.Value); 
            } 

            custom.Elements[i] = element; 
            break; 
        } 
    } 

    return custom; 
} 
4

0 に答える 0