SuperSparky has asked for the wisdom of the Perl Monks concerning the following question:

I have been pulling my hair out with this one, and it shouldn't be too difficult (but then again, when is SOAP simple?). I have been tasked with coding a SOAP server (NOT client) that incorporates WS-Security. I realize everyone must be pointing and laughing by now, but I have no choice with this. I've used the sample code in the SOAP::Lite docs as a starting point, but it always rejects ANY transaction with " mustUnderstand="1" " in it. I turn that off, I am able to read the header and process the WS header myself, but with that on, I don't get that far. SOAP::Lite just bounces it back saying it doesn't understand.

So... How do I get SOAP::Lite to "understand" or at least accept the envelope and give me a SOM to work with?

Please keep in mind I HAVE to write this server according to WSDL, and sample envelope given to me, as this is how the (very large) customer's system works. I also cannot tell them to turn off "mustUnderstand" either.

Luckily, their authentication mechanism is only "passwordText", so no need for decryption etc, as it is on HTTPS. I just need to get to the header once a SOM is given to me is all. I need to make SOAP::Lite ""understand" what it doesn't understand, and I cannot find anything anywhere about WS-Security for SERVERS. There's a boat load about clients, but nothing on servers.

Here's the sample posted envelope I am to make work (without the body for disclosure reasons):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-2 +00401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsse:UsernameToken wsu:Id="unt_5KBJ2WZxfTuiyZqf" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasi +s-200401-wss-wssecurity-utility-1.0.xsd"> <wsse:Username>SA_User</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis +-200401-wss-username-token-profile-1.0#PasswordText"> sa </wsse:Password> <wsse:Nonce>MC45NzcwNjA5MTgyMDk2OTIz</wsse:Nonce> <wsu:Created>2010-08-31T20:56:14Z</wsu:Created> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> blah... blah... blah... </soapenv:Body> </soapenv:Envelope>

This is my test server code running as a CGI on Apache

use strict; use SOAP::Transport::HTTP; SOAP::Transport::HTTP::CGI ->dispatch_to('Quote') ->handle; BEGIN { package Quote; use vars qw(@ISA); @ISA = qw(Exporter SOAP::Server::Parameters); use SOAP::Lite; use Data::Dumper::Simple; sub GetQuote { my @params = @_; print STDERR Dumper(\@params); return('ok'); } }

This is my test code to send my test envelope:

use strict; use LWP::UserAgent; use HTTP::Request::Common; my $ua = LWP::UserAgent->new(agent => 'perl post'); my $file = $ARGV[0]; my $msg = slurp_file($file); my $resp = $ua->request(POST 'http://localhost/perl/server.cgi', Content_Type => 'text/xml', Content => $msg); print $resp->error_as_HTML unless $resp->is_success; print $resp->as_string; exit(0); sub slurp_file { my $file = shift; # Read in a text file without using open return(do { local( @ARGV, $/ ) = $file ; <> }); }

Here's the response back:

<?xml version="1.0" encoding="UTF-8"?><soap:Envelope soap:encodingStyl +e="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://sche +mas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap +.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml +ns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><soap:F +ault><faultcode>soap:MustUnderstand</faultcode><faultstring>Unrecogni +zed header has mustUnderstand attribute set to 'true'</faultstring></ +soap:Fault></soap:Body></soap:Envelope>

I REALLY don't want to have to create my own SOAP handler to get around this. I'm hoping for some override, something.

UPDATE: I forgot to mention that the server (at least for the time being) must run in Perl 5.8.8 under CentOS 5.1.1. and Apache 2.2.3

Replies are listed 'Best First'.
Re: A dreaded SOAP server with ws-security
by runrig (Abbot) on Jun 30, 2015 at 22:23 UTC
Re: A dreaded SOAP server with ws-security
by FreeBeerReekingMonk (Deacon) on Jun 30, 2015 at 20:13 UTC

    WSRF::Lite from version 0.4 provides beta level support for signing and verifying SOAP messages using X509 digital certificates according to the OASIS standard for WS-Security. It has been tested with .NET and the Sun Web Service Developers Pack.
    Installing with CPAN is non trivial, as you require apache, openssl headers, some Crypt:: entries and more. (i.e. did not test it)

    See also WS-Security and Perl

      WSRF::Lite seems incomplete , even if it could be used , there are no examples

      See also WS-Security and Perl

      Um, no, nothing interesting to see there

Re: A dreaded SOAP server with ws-security
by Anonymous Monk on Jun 30, 2015 at 22:32 UTC

      Here's the progress:

      First I looked into everyone's advice, and my brain hurt. Note, it was all valid and good advice for a full blown and fully compliant SOAP server. However, this is for a limited and specific use. I knew there had to be a simpler solution... and I finally found it! In fact, it's so simple, I can't help but wonder why it isn't in the documentation. You simply add (before you instantiate the object):

      $SOAP::Constants::DO_NOT_CHECK_MUSTUNDERSTAND = 1;

      Yeah, my eye is twitching, and I'm giggling with glee that it was so simple. Grep was my friend here.

      Thanks folks, you're awesome.