Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

Îåêßíçóå áðü ôï ìÝëïò Τάσκος Γιώργος. Τελευταία δημοσίευση από το μέλος Τάσκος Γιώργος στις 30-04-2012, 15:19. Υπάρχουν 8 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  26-04-2012, 09:19 70136

    Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Καλησπέρα,

    Εδώ και δύο εβδομάδες έχω ταλαιπωρηθεί προσπαθώντας να καλέσω ένα Web Service, όπου δεν ελέγχω και δεν είναι .NET.
    Το Service απαιτεί να υπάρχει WS-Security authentication soap headers.
    Έχω ένα παράδειγμα το πως πρέπει να μοιάζει το request message, κι έχω καταφέρει με την βοήθεια του WSE 3.0 και με δύο τρεις αλλαγές
    να προσθέσω το add-in μέσα στο VS 2010.

    Ξεκινώντας να δώσω λίγο ιστορικό.
    Από την πρώτη στιγμή πήγα με την μέθοδο του Add Service Reference δημιουργώντας την Proxy κλάση derived από SoapHttpClientProtocol.
    Αυτό είχε τεράστιες δυσκολίες να διαχειριστώ το soap header και για να κάνω append τα WS-Security tags έπρεπε να δημιουργήσω web service extensions.
    Αυτό το πέτυχα μέχρι το σημείο που έπρεπε να βρω και τρόπο να κάνω generate το <Nonce>, <Timestamo> etc. Αν μπορεί κάποιος να βοηθήσει και σε αυτό καλοδεχούμενο.
    Ψάχνοντας για αυτό έπεσα πάνω στο WSE 3.0 το οποίο ομολογώ δεν είχα ξαναχρησιμοποιήσει, είδα ότι δεν υποστηριζόταν άλλο ποια μετά από το Visual Studio 2005!!!
    Τελικώς το έκανα εγκατάσταση και το έβαλα μέσα στο VS 2010, έφτιαξα μια class library .NET 2.0. Και αυτό με Update Web Reference μου δημιούργησε δύο proxy classes
    όπου η μία έκανε derive από την WebServiceClientProtocol και είχες τα πάντα για να φτιάξεις εύκολα το soap header.

    Κι εκεί που θα έπαιζαν όλα εύκολα, και το message γίνεται ακριβώς όπως μου το ζητάνε, παρατηρώ με το υπέροχο σωτήριο Fiddler (που αν και https μπόρεσε να με βοηθήσει),
    ότι ενώ έχω δώσει το Username, Password για το soap header UsernameSecurityToken, δεν έχει βάλει τις τιμές, έτσι παίρνω fault message Invalid Security.

    Παρακάτω το soap header από το Fiddler:

    <?xml version="1.0" encoding="utf-8"?>
    	<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    		xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    		xmlns:tns="http://tempuri.org/" 
    		xmlns:types="http://tempuri.org/encodedTypes" 
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    		xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    			<soap:Header>
    				<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustUnderstand="1">
    					<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="unt_PQxtsT0a8iV1KN2Y">
    						<wsse:Username></wsse:Username>
    						<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"></wsse:Password>
    						<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">i03CXze0uiIYG8+q8MhEMYHiMcL/NOpCwvEVpQ5xo+M=</wsse:Nonce>
    						<wsu:Created>2012-04-25T22:59:23Z</wsu:Created>
    					</wsse:UsernameToken>
    					<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    						<wsu:Created>2012-04-25T22:59:23Z</wsu:Created>
    						<wsu:Expires>2012-04-25T22:60:23Z</wsu:Expires>
    					</wsu:Timestamp>
    				</wsse:Security>
    			</soap:Header>
    Βλέπετε το πρόβλημα. Κατά τα άλλα όλα είναι υπέροχα με 3-3 γραμμές κώδικα.

    MessageServiceWse client = new MessageServiceWse();
    
    UsernameToken usernameToken = new UsernameToken(token.Username, token.Password, PasswordOption.SendPlainText);
    
    client.RequestSoapContext.Security.Tokens.Add(usernameToken);
    client.RequestSoapContext.Security.Timestamp.TtlInSeconds = 60;

    Ακόμη δοκίμασα με policies, προσπάθησα με config file του WSE, SendSecurityFilter, custom classes. Το αποτέλεσμα είναι πάντα ίδιο.
    Αφαιρώντας τον κώδικα ποιο πάνω, και πάλι μου κάνει generate το soap message με τα Security headers, πολύ περίεργο έτσι?

    Τέλος σκέφτηκα αν υπάρχει για τέτοιες δουλειές κάποιο 3rd party component. Όποιος γνωρίζει ας μου πει.

    Νομίζω πως αυτές είναι standard διαδικασίες και θα έπρεπε να παίζουν ποιο εύκολα. Αλλά αν δεν κάνω σωστά κάτι ας μας βοηθήσει το dotNETZone.

    Αμήν.

    Ευχαριστώ πολύ.



    Δημοσίευση στην κατηγορία: ,
  •  26-04-2012, 10:21 70137 σε απάντηση της 70136

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Και γιατί χρησιμοποιείς το καταργημένο WSE ??? Το WSE παρείχε υποστήριξη για WS-* στην προ-WCF εποχή. 

    Δοκίμασες με WCF πριν δοκιμάσεις να κάνεις την επικοινωνία με το χέρι? (Γιατί αυτό έκανες ουσιαστικά). Αν δοκίμασες και είχες πρόβλημα, ποιό ήταν αυτό? Υπάρχουν αρκετοί λόγοι που μπορεί να εμποδίσουν την επικοινωνία οι οποίοι δεν οφείλονται στην έλλειψη υποστήριξης για WCF:
    Μπορεί να μην έχεις κάνει σωστά το configuration του WCF. Πολύ συνηθισμένο πρόβλημα, μην πω ότι είναι αδύνατο να πετύχεις σωστό config με την πρώτη!
    1. Είναι σημαντικό να έχεις σωστά τα security parameters. Αυτή η απάντηση στο SO περιγράφει το σωστό συνδυασμό
    2. Μπορεί το web service να απαιτεί το ws:PasswordDigest προφίλ ενώ το WCF υποστηρίζει μόνο ws:PasswordText. Ο λόγος είναι ότι το digest δεν παρέχει σημαντικά καλύτερη ασφάλεια ενώ υπάρχουν άλλες τεχνικές για πολύ ισχυρότερη ασφάλεια.
      Εδώ περιγράφεται ακριβώς τί υποστηρίζεται και γιατί δεν υποστηρίζεται το digest.
      Αυτό το άρθρο περιγράφει πως να προσθέσεις εσύ υποστήριξη για το digest.
    3. Το WCF αρνείται να στείλει WS-Security headers με απλό http://. Ουσιαστικά οφείλεται στο #2
      ΑΝ δημιουργήσεις ένα custom binding, μπορείς να χρησιμοποιήσεις το AllowInsecureTransport attribute για να επιτρέψεις την επικοινωνία με http.
    4. Μπορεί το web service να ΜΗΝ υποστηρίζει WS-Security, κι ας σου λένε ότι το κάνει. Δες για παράδειγμα τί έπαθε ο Scott Hanselman όταν του δώσανε ένα web service που χρησιμοποιούσε "περίπου" WS-Security.
      Δεν νομίζω να φταίει αυτό, αλλά που ξέρεις
    Το WCF έχει δοκιμαστεί για interoperability με άλλες πλατφόρμες που υλοποιούν WS-Security. Δες πχ. το interoperability matrix για το .NET 4 WCF. Το WCF επικοινωνεί με WS-Security με WebLogic, Websphere, Netweaver.

    Το service που καλείς απαιτεί ντε και καλά το digest (ουσιαστικά θέλει το nonce) ? Μήπως δουλέψει αν το καλέσεις απλά με WCF και basicHttpBinding όπως στο #1?

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  26-04-2012, 13:00 70138 σε απάντηση της 70137

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Ευχαριστώ πολύ για την ξεκάθαρη απάντηση σου.

    1. Το άφησα στο proxy generation και ίσως για αυτό να απέτυχα με τον WCF client. Προσπάθησα με χαζές μεθόδους κι extensions όπου βρήκα.
        Αυτός ο σύνδεσμος δείχνει να έχει την λύση που χρειάζομαι. Άφησα τα customBindings που μου δημιούργησε, εμπιστευόμενος προφανώς ότι όλα
        θα γίνουν μαγικά :). No, don't think so. Είδα και πολλά παράπονα περί WCF client να κάνει κλήση σε non ASMX services και τέτοια. 
        Will try as soon as possible and let you know the result.
    2. Το service καλώς η κακώς απαιτεί PlainTextPassword, αλλά είναι https.

    Ναι το service απαιτεί όπως δείχνουν το digest (<Nonce />), θα τα δοκιμάσω όλα όσα περιγράφεις.

    Ευχαριστώ πολύ, μου έφτιαξες την μέρα, αν παίξει κιόλας, θα γίνω ένας ευτυχισμένος ακόμα άνθρωπος σήμερα :)

  •  27-04-2012, 22:34 70149 σε απάντηση της 70137

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)


    Δοκίμασα να κάνω implement τα παραπάνω.
    Με Add Service Reference δημιούργησα τον proxy.
    Αφού στο SO λέει ότι χρειάζομαι wsHttpBinding έκανα το εξής:

          <wsHttpBinding>
            <binding name="SoapWithAuth" useDefaultWebProxy="false">
              <security mode="TransportWithMessageCredential">
                <transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
              </security>
            </binding>
          </wsHttpBinding>
          <endpoint name="MessagePort"
              address="https://server:443/service/MessageService"
              binding="wsHttpBinding"
              bindingConfiguration="SoapWithAuth"
              contract="MessageServiceTest.MessageType" />
    Επειδή πρέπει να κάνω και accept το Server Certificate και να καλέσω το Service έχω γράψει το παρακάτω :

                ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) =>
                {
                    return true;
                };
    
                ServicePointManager.Expect100Continue = false;
    
                using (MessageTypeClient client = new MessageTypeClient())
                {
                    
                    client.ClientCredentials.UserName.UserName = token.Username;
                    client.ClientCredentials.UserName.Password = token.Password;
                    
                    MessageRequest req = new MessageRequest
                    {
                        xmlMessage = documentXml
                    };
    
                    client.Open();
                    
                    RequestResult result = client.processMessage(req);
    
                    client.Close();
    
                    if (result.resultState.status != RequestState.OK)
                    {
                        throw new MessageException(ResultToString(result.resultState), ErrorsToString(result.ProcessingErrors));
                    }
                }
    Και παίρνω exception στο client.Open().

    System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
    
    Server stack trace: 
       at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
    
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
       at System.ServiceModel.ClientBase`1.Close()
       at System.ServiceModel.ClientBase`1.System.IDisposable.Dispose()
    Σας λέει τίποτα?
    Ενώ το state είναι Created! Δεν πρέπει να γίνει Open?

    Ευχαριστώ.



  •  27-04-2012, 22:45 70150 σε απάντηση της 70149

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Χμμμ, έβγαλα το using κι έπαιξε!!! μου φένεται περίεργο όμως.
  •  27-04-2012, 23:19 70151 σε απάντηση της 70150

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Από ότι βλέπω πρέπει να παίζει. Θα το κάνω καλό test και θα δώσω την λύση.

    Ευχαριστώ.


  •  29-04-2012, 19:58 70164 σε απάντηση της 70151

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Προσθέτοντας απλά αυτό το Security tag έπαιξε as expected. Και δεν χρειάζεται το Nonce στην περίπτωση μου.
    Έτσι λένε απλά, τουλάχιστον για την ώρα.

    <security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport" requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
                <secureConversationBootstrap />
              </security>
    Ευχαριστώ για την βοήθεια.

  •  30-04-2012, 13:33 70181 σε απάντηση της 70150

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Τάσκος Γιώργος:
    Χμμμ, έβγαλα το using κι έπαιξε!!! μου φένεται περίεργο όμως.
    H Dispose εσωτερικά καλεί την Close, φαίνεται και στο call stack. Ουσιαστικά προσπαθείς να κλείσεις δύο φορές το ίδιο αντικείμενο. Βγάλε το Close, όχι το using, διαφορετικά θα πρέπει να κλείσεις τον κώδικα σου σε try/finally και να περάσεις το Close στο finally -  ό,τι κάνει αυτόματα για σένα το using.

    Τάσκος Γιώργος:
    Προσθέτοντας απλά αυτό το Security tag

    Δεν έχεις προσθέσει απλά το security tag, έχεις βάλει κάμποσα πράγματα μέσα. Αυτά δεν τα βάζει μόνο του το WCF ή μήπως απαιτεί το άλλο service κάποια attributes που δεν μπαίνουν αυτόματα?

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  30-04-2012, 15:19 70183 σε απάντηση της 70181

    Απ: Web Service απαιτεί WS-Security header. Το Username και Password tags είναι άδεια. (WSE 3.0)

    Ναι, το using είναι καλύτερα, θα το αλλάξω.

    Η αλήθεια είναι πως όχι, τα customBinding μου τα έφτιαξε το proxy όπως και στις αρχές και μου έβαλε και κάποια σχόλια για attributes που δεν καταλάβαινε.
    Έφτιαξα αυτό το Security tag με αυτά τα attributes που βλέπεις, και είμαι χαρούμενος :)

    Τελικά ήταν ποιο εύκολο κι ο δρόμος που είχα πάρει λάθος, δεν υπήρχε λόγος για WSE 3.0 και ιστορίες.
    WCF από ότι δείχνει είναι καλό και με non WCF services. Και ήταν η πρώτη φορά που έπρεπε να το χρησιμοποιήσω για τέτοιο service.
    Όταν ελέγχεις και τις δύο πλευρές συνήθως όλα είναι ποιο εύκολα!

    ROCKS! 

    Thanx.

Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems