简体   繁体   English

标头上的类型身份验证具有未定义的属性{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id

[英]Authentication of type on Header had undefined attribute {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id

Have been struggling for last few days with this error 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 while invoking a service call from a C# WCF client (targeting .Net 4.5 framework) to a Java Soap Service hosted externally with end-to-end encryption (both client and service certificates are used). 最近几天一直在因该错误而苦苦挣扎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同时从C#WCF客户端(目标为.Net 4.5框架)调用服务调用到外部托管的Java Soap Service(端到端加密)(客户端和服务)使用证书)。 When I tested the service using SoapUI with a JKS file, request was processed successfully. 当我使用带有JKS文件的SoapUI测试服务时,请求已成功处理。

So to see what's difference between the two requests, I did the followings: 为了查看两个请求之间的区别,我做了以下工作:

  1. Used Fiddler Inspector to capture two requests, one from SoapUI which was successful and one from C# which failed with 500 error 使用Fiddler Inspector捕获两个请求,一个来自SoapUI的请求成功,另一个来自C#的失败,错误为500
  2. Extracted these two Xml messages into two C# classes (named them RequestByJava and RequestByDotNet, respectively) using the VS2017 feature Edit/Paste Special/Paste Xml as Classes. 使用VS2017功能“编辑/粘贴特殊/粘贴Xml作为类”,将这两个Xml消息提取到两个C#类(分别命名为RequestByJava和RequestByDotNet)中。
  3. Use XmlSerializer to de-serialize the two requests into the two objects of the types created in 2) and compared their properties. 使用XmlSerializer将两个请求反序列化为2)中创建的类型的两个对象,并比较它们的属性。
  4. With the Soap error message in mind, I narrowed down the difference between two Authentication headers - interestingly there is one extra property "Id" in the RequestByDotNet object whereas the RequestByJava object does not have. 考虑到Soap错误消息,我缩小了两个Authentication标头之间的差异-有趣的是,RequestByDotNet对象中有一个额外的属性“ Id”,而RequestByJava对象中没有。 And the 500 Soap error message seemed to indicate that there was a schema validation error due to that undefined element "Id" 并且500 Soap错误消息似乎表明由于未定义元素“ Id”而导致架构验证错误
  5. Also noticed that the RequestByDotNet. 还注意到了RequestByDotNet。 Header.Security.BinarySecurityToken.ValueType ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0# X509v3 " but RequestByJava (SoapUI) has a different ValueType " http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0# X509PKIPathv1 " Header.Security.BinarySecurityToken.ValueType =“ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0# X509v3 ”,但RequestByJava(SoapUI)具有不同的ValueType“ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0# X509PKIPathv1
  6. Another difference, not sure it matters, is that the Request from .net codes has a " mustunderstand " value under the Header.Security set to true while the one from Java does not. 另一个不确定的问题是,来自.net代码的Request在Header.Security下具有一个“ mustunderstand ”值,而Java中则没有。

My questions are: 我的问题是:

  1. Why is the difference? 为什么有区别?
  2. How can this be fixed without having to write a Java client? 无需编写Java客户端,如何解决此问题?

Some codes used binding and endpoint behavior: 一些代码使用了绑定和端点行为:

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();
        }
    }

Thanks for your time! 谢谢你的时间! Your help will be highly appreciated. 非常感谢您的帮助。

@jdweng Yes, I did; @jdweng是的,我做到了; here were two request bodies, first from .Net and 2nd from SoapUI: 这是两个请求主体,第一个来自.Net,第二个来自SoapUI:

.Net Request: .Net请求:

<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 Request: SoapUI请求:

(somehow it won't let me past whole xml here.. ) (以某种方式,它不会让我过去整个xml。)

Well, my colleague helped me figure out way to remove the extra headers from the request before it was posted to the Java SOAP service endpoint - the key was to use IClientMessageInspector and implement some logic in the BeforeSendRequest to remove the unwanted headers that were rejected by the service provider; 好吧,我的同事帮助我找出了一种方法,可以在将请求发布到Java SOAP服务端点之前从请求中删除多余的标头-关键是使用IClientMessageInspector并在BeforeSendRequest中实现一些逻辑以删除被拒绝的标头服务提供者; then add a custom FormattingBehavior class to inherit from IEndpointBheavior and in the IEndPointBehavior. 然后添加自定义FormattingBehavior类从IEndpointBheavior并在IEndPointBehavior继承。 ApplyClientBehavior , attach the MyClientMessageInspector; ApplyClientBehavior ,附加MyClientMessageInspector; finally add the customer endpoint behavior to the web service client. 最后将客户端点行为添加到Web服务客户端。 Here are the codes: 以下是代码:

  1. Where and how to remove unwanted request headers : 在何处以及如何删除不需要的请求标头

     public class MyClientMessageInspector : IClientMessageInspector 

    { public MyClientMessageInspector(ServiceEndpoint endpoint) { } {public 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. Where and how to use the custom ClientMessageInspector : 在何处以及如何使用自定义ClientMessageInspector

      internal class MyFaultFormatterBehavior : IEndpointBehavior 

    { ... {...

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

    } }

  3. Where and how to attach custom EndpointBehavior: 在何处以及如何附加自定义EndpointBehavior:

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

    //Set client certificate //设置客户端证书
    client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.Root, X509FindType.FindByThumbprint, "xxxxxxxxxx"); 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. What else? 还有什么? In the proxy classes, need to set the Authentication ProtectionLevel to None while on the Service level it needs to be set as ProtectionLevel.Sign: 在代理类中,需要将Authentication ProtectionLevel设置为None,而在Service级别上则需要将其设置为ProtectionLevel。

Request level: 要求等级:

    [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;

Service (Interface) Level: 服务(接口)级别:

    [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
{

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 必须了解标头http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd的检查失败:安全 - Must Understand check failed for header http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd : Security 无法处理 mustUnderstand 标头:{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}安全。 返回故障 - Could not handle mustUnderstand headers: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security. Returning fault 如何为{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}添加虚拟SOAPHandler? - How to add a dummy SOAPHandler for {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}? SOAPFaultException “MustUnderstand 标头 (oasis-200401-wss-wssecurity-secext-1.0.xsd) 不被理解” - SOAPFaultException “MustUnderstand headers (oasis-200401-wss-wssecurity-secext-1.0.xsd) are not understood” 使用 CXF 和 WSS4J for X509Certificate 的 SOAP WsSecurity 数字签名 - SOAP WsSecurity Digital Signing using CXF and WSS4J for X509Certificate 如何直接打开一个websocket到一个wss:in Java - How to open a websocket directly to a wss: in Java OWL API是否支持Oasis XML目录? - Does the OWL API Support Oasis XML Catalogs? 使用 WSS4J (SOAP) 在 CXF WebServices 中实现身份验证 - Implement Authentication in CXF WebServices using WSS4J (SOAP) 使用 WSS4J 签署 XML。 没有 ID 为“noXMLSig”的消息 - Sign XML with WSS4J. No message with ID "noXMLSig" 将我的自定义拦截器放在 cxf 中的默认 org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor 之后 - place my custom interceptor after default org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor in cxf
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM