2017-08-26 38 views
1

已經在爲最後在調用從C#WCF客戶端(以.Net 4.5框架爲目標)的服務調用到使用端對端加密(使用客戶端和服務證書)的外部託管的Java Soap服務時,出現此錯誤Authentication of type {http://service.soap.xcompany.com}AuthenticationHeader had undefined attribute {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id的幾天。當我使用帶有JKS文件的SoapUI測試服務時,請求已成功處理。Header上的類型認證具有未定義的屬性{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id

所以,看看有什麼兩個請求之間的區別,我做了以下內容:

  1. 使用提琴手檢查器捕獲兩個要求,一個從了SoapUI這是成功的,一個從C#失敗並500錯誤
  2. 使用VS2017功能Edit/Paste Special/Paste Xml as Classes將這兩個Xml消息提取到兩個C#類(分別命名爲RequestByJava和RequestByDotNet)。
  3. 使用XmlSerializer將兩個請求反序列化爲2)中創建的兩個類型的對象,並比較它們的屬性。
  4. 考慮到Soap錯誤消息,我縮小了兩個Authentication標頭之間的區別 - 有趣的是,RequestByDotNet對象中有一個額外的屬性「Id」,而RequestByJava對象沒有。並且500 Soap錯誤消息似乎表明由於未定義的元素「Id」而存在架構驗證錯誤
  5. 也注意到RequestByDotNet。 Header.Security.BinarySecurityToken.ValueType =「http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0# X509v3」但RequestByJava(了SoapUI)具有不同的值類型「http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1
  6. 另一個不同之處,不知道它的問題,是從.NET代碼的要求有Header.Security下「的mustUnderstand」值設置爲true,而一個從Java不是。

我的問題是:

  1. 爲什麼不一樣?
  2. 如何解決這個問題而無需編寫Java客戶端?

一些代碼使用的綁定和端點的行爲:

private static CustomBinding BuildCustomBinding() 
    { 
     var binding = new CustomBinding(); 

     var textMessageEncoding = new TextMessageEncodingBindingElement() 
     { 
      MessageVersion = MessageVersion.Soap11 

     }; 

     var securityBindingElement = 
      SecurityBindingElement.CreateMutualCertificateBindingElement(
       MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, true); 


     binding.Elements.AddRange(textMessageEncoding, securityBindingElement, new HttpsTransportBindingElement()); 

     return binding; 
    } 


private static void CallAccountService() 
    { 
     //credential for test 
     const string applId = "testuser"; 
     const string pwd = "password"; 


     //for client certificate, import client.pfx to LocalMachine's Trusted Root Certification Authorities and make sure the thumbprint matches 
     var client = new NOLWSAccountSvc.WSAccountv1Client(BuildCustomBinding(), GetAccountServiceEndpointAddress()); 
     client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, 
      StoreName.Root, X509FindType.FindByThumbprint, "thumbprintvalue"); 

     //for service certificate, import service-provider.cer to same store location and store name and make sure the thumbprint matches 
     client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.Root, 
      X509FindType.FindByThumbprint, "thumprintvalue"); 
     client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = 
      X509CertificateValidationMode.PeerOrChainTrust; 

     client.Open(); 
     var header = new NOLWSAccountSvc.AuthenticationHeader() 
     { 
      application_id = applId, 
      password = pwd 
     }; 

     var getActiveAccountsFunc = new NOLWSAccountSvc.getActiveAccounts() { applRef = "softact-dev", resetRows = true }; 

     try 
     { 
      var response = client.getActiveAccounts(header, getActiveAccountsFunc); 
      Console.WriteLine(response.moreData); 
     } 
     catch (Exception ex) 
     { 

      Console.WriteLine(ex.Message); 
     } 

     finally 
     { 
      client.Close(); 
     } 
    } 

感謝您的時間!您的幫助將受到高度讚賞。

+0

您是否比較了工作請求和非工作請求的主體。看起來這兩個請求都是使用509加密加密的。請參閱wiki:https://en.wikipedia.org/wiki/X.509 – jdweng

+0

看起來證書的命名約定是不同的,但是是等同的:X.509 v3證書標準的配置文件,如RFC 5280中所述,通常稱爲公鑰基礎設施PKIX(X.509)。實際證書一定有問題。你必須看看證書本身。 – jdweng

回答

0

@jdweng是的,我做了;這裏有兩個請求主體,首先從.Net和第二從了SoapUI:

淨請求:

<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><h:Authentication u:Id="_2" xmlns:h="http://service.soap.xcompany.com" xmlns="http://service.soap.xcompany.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><application_id>testuserid</application_id><password>testpassword</password></h:Authentication><ActivityId CorrelationId="d7085e6f-b757-46e8-b3eb-319a51d568a3" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId><VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo8DAzaQVkApDpl1Tc1YTHQwAAAAAMbeMEvBLCUqoD7kEDPHDKYukgggNOf5FtHBB/Sa7ggkACQAA</VsDebuggerCausalityData><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><o:BinarySecurityToken u:Id="uuid-eb310312-396a-4d00-8922-f77de97138cb-3" 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">MIIDYzCCAkugAwIBAgIEaGKzJDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJ1czEPMA0GA1UEChMGU3ByaW50MREwDwYDVQQLEwhQcm9qZWN0czEMMAoGA1UECxMDQk1QMQwwCgYDVQQLEwNUUEExEzARBgNV</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>WCpRwVjx89ceVctR8lp9LNGKHeA=</DigestValue></Reference><Reference URI="#_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>8/PErh8BL9To5zazpP9CbPFTAa8=</DigestValue></Reference></SignedInfo><SignatureValue>hOtpz7lXvZPPbBD6sV1hxyx3Hc39vj0q2GYKMd8oQbgTbbuKC7QKcZOjktqUxayrzc6h/V0j7Kx3APPONe4F3A2581nK4AQ72yYonsaeXQW0yzSxW/VTsN04uoqCP6IpKXqlAz40VeWGUPJOeGthCKy/9A+NSuqS</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-eb310312-396a-4d00-8922-f77de97138cb-3"/></o:SecurityTokenReference></KeyInfo></Signature></o:Security></s:Header><s:Body u:Id="_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><getActiveAccounts xmlns="http://service.soap.xcompany.com"><applRef>dev</applRef><resetRows>false</resetRows></getActiveAccounts></s:Body></s:Envelope> 

了SoapUI請求:

(不知它不會讓我過去整個XML在這裏..)

0

好了,我的同事幫我想出辦法從要求刪除多餘的頭,然後才發佈到Java的SOAP服務端點 - 關鍵是使用IClientMessageInspector和實現一些邏輯在BeforeSendRequest刪除被服務提供商拒絕的不需要的頭文件;然後添加一個自定義的FormattingBehavior類以繼承IEndpointBheavior和IEndPointBehavior中的ApplyClientBehavior,附加MyClientMessageInspector;最後將客戶端點行爲添加到Web服務客戶端。下面是代碼:

  1. 在哪裏以及如何刪除不想要的請求頭

    public class MyClientMessageInspector : IClientMessageInspector 
    

    { 公共MyClientMessageInspector(ServiceEndpoint終點) { }

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
        //Console.WriteLine(request.ToString()); 
    
        var lstUnwantedStuff = new[] 
        { 
         new KeyValuePair<string, string>("Action", "http://www.w3.org/2005/08/addressing"), 
         new KeyValuePair<string, string>("VsDebuggerCausalityData", 
          "http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink") 
        }; 
    
        foreach (var kv in lstUnwantedStuff) 
        { 
         var indexOfUnwantedHeader = request.Headers.FindHeader(kv.Key, kv.Value); 
         if (indexOfUnwantedHeader>=0) 
         { 
          request.Headers.RemoveAt(indexOfUnwantedHeader); 
         } 
        } 
    

    。 ..

  2. 何處以及如何使用自定義ClientMessageInspector

    internal class MyFaultFormatterBehavior : IEndpointBehavior 
    

    { ...

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
        clientRuntime.MessageInspectors.Add(new MyClientMessageInspector(endpoint)); 
    } 
    

    }

  3. 在哪裏以及如何定製EndpointBehavior附加:

    private static void CallAccountService() 
    { 
    
        var client = new WSAccountv1Client(BuildCustomBinding(), GetAccountServiceEndpointAddress()); 
    

    //設置客戶證書
    client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.Root,X509FindType.FindByThumbprint, 「XXXXXXXXXX」);

    //for service certificate 
        client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, 
         X509FindType.FindByThumbprint, "xxxxxxxxxxxxxxxxy"); 
        client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = 
         X509CertificateValidationMode.PeerOrChainTrust; 
    
        //add faultformattingbehavior so we can intercept the fault reply message 
        client.Endpoint.EndpointBehaviors.Add(new MyFaultFormatterBehavior()); 
    
        client.Open(); 
        var header = new AuthenticationHeader() 
        { 
         application_id = applId, 
         password = pwd 
        }; 
    
        var getActiveAccountsFunc = new getActiveAccounts() { applRef = "test", resetRows = true }; 
    
        try 
        { 
         //MyClientMessageInspector.BeforeSendRequest is entered when this called is made 
         var response = client.getActiveAccounts(header, getActiveAccountsFunc); 
         Console.WriteLine(response.moreData); 
        } 
        catch (Exception ex) 
        { 
    
         Console.WriteLine(ex.Message); 
        } 
    
        finally 
        { 
         client.Close(); 
        } 
    } 
    
  4. 還有什麼? 在代理類,需要身份驗證的ProtectionLevel設置爲無,而在服務水平需要將其設置爲ProtectionLevel.Sign:

請求級別:

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] 
[System.ServiceModel.MessageContractAttribute(IsWrapped = false)] 
public partial class getActiveAccountsRequest 
{ 

    [System.ServiceModel.MessageHeaderAttribute(Namespace = "http://service.xcompany.com" 
     , ProtectionLevel = System.Net.Security.ProtectionLevel.None 
     )] 
    public AuthenticationHeader Authentication; 

服務(接口)級別:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] 
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://service.xcompany.com", 
    ConfigurationName = "WSAccount" 
    , ProtectionLevel = ProtectionLevel.Sign 
    )] 
public interface WSAccount 
{ 
相關問題