Καλησπέρα,
Εδώ και δύο εβδομάδες έχω ταλαιπωρηθεί προσπαθώντας να καλέσω ένα 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.
Αμήν.
Ευχαριστώ πολύ.