2016-05-13 17 views
0

Ich versuche, einen funktionierenden CURL-Befehl mit LWP in Perl neu zu erstellen, und ich bekomme einen 401 nicht autorisierten Fehler von LWP. Der Befehl sendet JSON an eine bestimmte URL, wie im folgenden Code zu sehen ist. Der FQDN, die IP-Adresse, der Port und der Pfad des Servers sind korrekt und identisch zwischen curl und Perl, ebenso wie die Anmeldeinformationen und der Realm. Jede Hilfe wäre willkommen - danke!Perl LWP nicht autorisiert, während Curl Ok

Unten ist die Arbeits Syntax in cURL und Debug-Ausgabe:

#curl -v -k -u "USERNAME:PASSWORD" -X POST <SERVER_URL> -d '<JSON CONTENT>'; 

* About to connect() to <SERVER_URL> port 443 (#0) 
* Trying <SERVER_IP>... connected 
* Connected to <SERVER_URL> (<SERVER_IP>) port 443 (#0) 
* Initializing NSS with certpath: sql:/etc/pki/nssdb 
* warning: ignoring value of ssl.verifyhost 
* skipping SSL peer certificate verification 
* SSL connection using TLS_DHE_RSA_WITH_AES_256_CBC_SHA 
* Server certificate: 
*  subject: [REDACTED] 
*  start date: Apr 21 00:00:00 2016 GMT 
*  expire date: Apr 21 23:59:59 2019 GMT 
*  common name: <SERVER_URL> 
*  issuer: [REDACTED] 
* Server auth using Basic with user '<USERNAME>' 
> POST <SERVER_PATH> HTTP/1.1 
> Authorization: Basic <BASE64-ENCODED USERNAME:PASSWORD> 
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 
> Host: <SERVER_URL> 
> Accept: */* 
> Content-Length: 144 
> Content-Type: application/x-www-form-urlencoded 
> 
< HTTP/1.1 200 OK 
< Date: Fri, 13 May 2016 13:48:42 GMT 
< Server: Apache 
< Content-Type: application/json 
< Content-Length: 256 
< 
* Connection #0 to host <SERVER_URL> left intact 
* Closing connection #0 

Aktualisiert Perl-Code und Output pro Steffen Vorschlag. I korrigiert einen anfänglichen Fehler zu zitieren und auch der Header an den LWP Befehl POST Accept hinzugefügt:

use strict; 
use warnings; 
use LWP::UserAgent; 
use Data::Dumper; 

my $server_root_with_port = "<FQDN>:443"; 
my $url = "<SERVER_URL>"; 
my $realm = "<SERVER_REALM>"; 
my $json = "<JSON CONTENT>"; 
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 }); 
$ua->credentials($server_root_with_port,$realm,$username=>$password); 
$response = $ua->post($url, 'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => '*/*', 'Content' => $json); 
print Dumper $response; 

exit; 

$VAR1 = bless({ 
     '_protocol' => 'HTTP/1.1', 
     '_content' => '', 
     '_rc' => '400', 
     '_headers' => bless({ 
        'connection' => 'close', 
        'client-response-num' => 1, 
        'date' => 'Mon, 16 May 2016 14:18:59 GMT', 
        'client-ssl-cert-issuer' => '[REDACTED]', 
        'client-ssl-cipher' => 'AES128-SHA256', 
        'client-peer' => '<SERVER_IP>:443', 
        'content-length' => '0', 
        '::std_case' => { 
           'client-date' => 'Client-Date', 
           'client-response-num' => 'Client-Response-Num', 
           'client-ssl-cert-subject' => 'Client-SSL-Cert-Subject', 
           'client-ssl-cert-issuer' => 'Client-SSL-Cert-Issuer', 
           'client-ssl-cipher' => 'Client-SSL-Cipher', 
           'client-peer' => 'Client-Peer', 
           'client-ssl-socket-class' => 'Client-SSL-Socket-Class' 
          }, 
        'client-date' => 'Mon, 16 May 2016 14:18:59 GMT', 
        'client-ssl-cert-subject' => '[REDACTED]', 
        'server' => 'Apache', 
        'client-ssl-socket-class' => 'IO::Socket::SSL' 
         }, 'HTTP::Headers'), 
     '_previous' => bless({ 
        '_protocol' => 'HTTP/1.1', 
        '_content' => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
          <html><head> 
          <title>401 Unauthorized</title> 
          </head><body> 
          <h1>Unauthorized</h1> 
          <p>This server could not verify that you 
          are authorized to access the document 
          requested. Either you supplied the wrong 
          credentials (e.g., bad password), or your 
          browser doesn\'t understand how to supply 
          the credentials required.</p> 
          </body></html> 
          ', 
        '_rc' => '401', 
        '_headers' => bless({ 
           'connection' => 'close', 
           'client-response-num' => 1, 
           'date' => 'Mon, 16 May 2016 14:18:59 GMT', 
           'client-ssl-cert-issuer' => '[REDACTED]', 
           'client-ssl-cipher' => 'AES128-SHA256', 
           'client-peer' => '<SERVER_IP>:443', 
           'content-length' => '381', 
           '::std_case' => { 
              'client-date' => 'Client-Date', 
              'client-response-num' => 'Client-Response-Num', 
              'client-ssl-cert-subject' => 'Client-SSL-Cert-Subject', 
              'title' => 'Title', 
              'client-ssl-cert-issuer' => 'Client-SSL-Cert-Issuer', 
              'client-ssl-cipher' => 'Client-SSL-Cipher', 
              'client-peer' => 'Client-Peer', 
              'client-ssl-socket-class' => 'Client-SSL-Socket-Class' 
             }, 
           'client-date' => 'Mon, 16 May 2016 14:18:59 GMT', 
           'content-type' => 'text/html; charset=iso-8859-1', 
           'client-ssl-cert-subject' => '[REDACTED]', 
           'www-authenticate' => 'Basic realm="<SERVER_REALM>"', 
           'title' => '401 Unauthorized', 
           'server' => 'Apache', 
           'client-ssl-socket-class' => 'IO::Socket::SSL' 
            }, 'HTTP::Headers'), 
        '_msg' => 'Unauthorized', 
        '_request' => bless({ 
           '_content' => '<JSON_CONTENT>', 
           '_uri' => bless(do{\(my $o = '<SERVER_URL>')}, 'URI::https'), 
           '_headers' => bless({ 
               'user-agent' => 'libwww-perl/6.15', 
               'content-type' => 'application/x-www-form-urlencoded', 
               'accept' => '*/*', 
               'content-length' => 144, 
               '::std_case' => { 
                'if-ssl-cert-subject' => 'If-SSL-Cert-Subject' 
                 } 
              }, 'HTTP::Headers'), 
           '_method' => 'POST', 
           '_uri_canonical' => $VAR1->{'_previous'}{'_request'}{'_uri'} 
            }, 'HTTP::Request') 
         }, 'HTTP::Response'), 
     '_msg' => 'Bad Request', 
     '_request' => bless({ 
        '_protocol' => undef, 
        '_content' => '<JSON_CONTENT>', 
        '_uri' => bless(do{\(my $o = '<SERVER_URL>')}, 'URI::https'), 
        '_headers' => bless({ 
            'user-agent' => 'libwww-perl/6.15', 
            'content-type' => 'application/x-www-form-urlencoded', 
            'accept' => '*/*', 
            'content-length' => 144, 
            'authorization' => '<BASE64-ENCODED USERNAME:PASSWORD>', 
            '::std_case' => { 
             'if-ssl-cert-subject' => 'If-SSL-Cert-Subject' 
              } 
           }, 'HTTP::Headers'), 
        '_method' => 'POST', 
        '_uri_canonical' => $VAR1->{'_request'}{'_uri'} 
         }, 'HTTP::Request') 
      }, 'HTTP::Response'); 

Perl Revision # 1:

use strict; 
use warnings; 
use LWP::UserAgent; 
use HTTP::Request::Common; 
use Data::Dumper; 

my $fqdn_port = "<FQDN>:443"; 
my $url  = "<URL>"; 
my $realm  = "<REALM>"; 
my $username = "<USERNAME>"; 
my $password = "<PASSWORD>"; 
my $json  = "<JSON_CONTENT>"; 

my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 }); 

#$ua->credentials($fqdn_port,$realm,$username=>$password); 
#my $response = $ua->post($url, 'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => '*/*', Content => $json); 

my $request = HTTP::Request->new('POST',$url); 
$request->header('Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => '*/*'); 
$request->authorization_basic($username,$password); 
$request->content($json); 

my $response = $ua->request($request); 

print Dumper $response; 

exit; 


$VAR1 = bless({ 
     '_protocol' => 'HTTP/1.1', 
     '_content' => '', 
     '_rc' => '400', 
     '_headers' => bless({ 
        'connection' => 'close', 
        'client-response-num' => 1, 
        'date' => 'Mon, 16 May 2016 15:41:10 GMT', 
        'client-ssl-cert-issuer' => '[REDACTED]', 
        'client-ssl-cipher' => 'AES128-SHA256', 
        'client-peer' => '<SERVER_IP>:443', 
        'content-length' => '0', 
        '::std_case' => { 
           'client-date' => 'Client-Date', 
           'client-response-num' => 'Client-Response-Num', 
           'client-ssl-cert-subject' => 'Client-SSL-Cert-Subject', 
           'client-ssl-cert-issuer' => 'Client-SSL-Cert-Issuer', 
           'client-ssl-cipher' => 'Client-SSL-Cipher', 
           'client-peer' => 'Client-Peer', 
           'client-ssl-socket-class' => 'Client-SSL-Socket-Class' 
          }, 
        'client-date' => 'Mon, 16 May 2016 15:41:10 GMT', 
        'client-ssl-cert-subject' => '[REDACTED]', 
        'server' => 'Apache', 
        'client-ssl-socket-class' => 'IO::Socket::SSL' 
         }, 'HTTP::Headers'), 
     '_msg' => 'Bad Request', 
     '_request' => bless({ 
        '_content' => '<JSON_CONTENT>', 
        '_uri' => bless(do{\(my $o = '<URL>')}, 'URI::https'), 
        '_headers' => bless({ 
            'user-agent' => 'libwww-perl/6.15', 
            'content-type' => 'application/x-www-form-urlencoded', 
            'accept' => '*/*', 
            '::std_case' => { 
             'if-ssl-cert-subject' => 'If-SSL-Cert-Subject' 
              }, 
            'authorization' => 'Basic <BASE64-ENCODED USERNAME:PASSWORD>' 
           }, 'HTTP::Headers'), 
        '_method' => 'POST', 
        '_uri_canonical' => $VAR1->{'_request'}{'_uri'} 
         }, 'HTTP::Request') 
      }, 'HTTP::Response'); 
+0

verify_hostname => 1 sollte => 0 sein, das würde passen curl -k – gfunk

Antwort

2

TL; TR: immeruse strict !!

$response = $ua->post($url, Content-Type => 'application/json', Content => $json); 

Sie haben verpasst um Content-Type zu zitieren, die von use strict erkannt worden wäre. Das Ergebnis davon ist ein seltsamer Kopf 0 Sie in der Debug-Ausgabe sehen:

'content-type' => 'application/x-www-form-urlencoded', 
'0' => 'application/json', 
'content-length' => 144, 

Und das bedeutet auch, dass die Einstellung des Inhaltstypen falsch ist. Dies zusammen führt zu der Server Ihre Anforderung nicht akzeptieren:

'_rc' => '400', 
    ... 
    '_msg' => 'Bad Request', 

Um zu verstehen, was auf dem hier geschieht, was Perl sieht tatsächlich in einem solchen Code:

$ perl -MO=Deparse -e 'my %x = (Content-Type => 1, Foo => 2)' 
my(%x) = ('Content' - 'Type', 1, 'Foo', 2); 

Dies zeigt, dass es die nicht notierten Content-Type interpretieren wird als 'Content' - 'Type'. Und da die Subtraktion für Strings nicht definiert ist, werden sie in eine ganze Zahl umgewandelt, d. H. 0. Das heißt, das Ergebnis ist 0 (0-0).

Wenn strikte Verwendung erhalten Sie stattdessen:

perl -Mstrict -e 'my %x = (Content-Type => 1, Foo => 2)'                                 
Bareword "Content" not allowed while "strict subs" in use at -e line 1.                                   
Execution of -e aborted due to compilation errors. 
+0

Steffen - ich meinen Code aktualisiert, wie Sie vorgeschlagen, Content-Type mit einfachen Anführungszeichen gesetzt, so dass die resultierende Syntax liest ‚Content-Type '=>' Anwendung/Json 'und mit strict Ich bekomme keinen Fehler, aber ich bekomme immer noch einen 401 nicht autorisierten Fehler. – dthumb

+0

@dthumb: Bitte aktualisieren Sie den Code und Debug-Ausgabe in Ihrer Frage, um den aktuellen Zustand widerzuspiegeln. –

+0

Aktualisierte ursprüngliche Frage mit den Änderungen wie vorgeschlagen - nicht mehr den fehlerhaften Header sehen, aber immer noch eine 401 nicht autorisierte Rückkehr vom Server. Vielen Dank. – dthumb

0

eine Lösung gefunden - vielleicht nicht die eleganteste, aber es funktioniert der Trick. Beendet mithilfe von HTTP :: Request :: Common, um das Autorisierungsproblem zu umgehen, und hat das Anführungszeichen für die JSON-Variable umgekehrt, um die fehlerhafte 400-Anforderung und den Erfolg zu minimieren - eine korrekte Rückgabe vom Server zu erhalten! Danke für die Hilfe @steffen_ullrich.

use strict; 
use warnings; 
use LWP::UserAgent; 
use HTTP::Request::Common; 
use Data::Dumper; 

my $fqdn_port = "<FQDN>:443"; 
my $url  = "<URL>"; 
my $realm  = "<REALM>"; 
my $username = "<USERNAME>"; 
my $password = "<PASSWORD>"; 
my $json  = '<JSON_CONTENT>'; 

my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 }); 
my $request = HTTP::Request->new('POST',$url); 
$request->header('Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => '*/*'); 
$request->authorization_basic($username,$password); 
$request->content($json); 

my $response = $ua->request($request); 
print Dumper $response; 
exit; 


$VAR1 = bless({ 
     '_protocol' => 'HTTP/1.1', 
     '_content' => '<RETURN JSON FROM SERVER>', 
     '_rc' => '200', 
     '_headers' => bless({ 
        'connection' => 'close', 
        'client-response-num' => 1, 
        'date' => 'Mon, 16 May 2016 16:07:07 GMT', 
        'client-ssl-cert-issuer' => '[REDACTED]', 
        'client-ssl-cipher' => 'AES128-SHA256', 
        'client-peer' => '<SERVER_IP>:443', 
        'content-length' => '233', 
        '::std_case' => { 
           'client-date' => 'Client-Date', 
           'client-response-num' => 'Client-Response-Num', 
           'client-ssl-cert-subject' => 'Client-SSL-Cert-Subject', 
           'client-ssl-cert-issuer' => 'Client-SSL-Cert-Issuer', 
           'client-ssl-cipher' => 'Client-SSL-Cipher', 
           'client-peer' => 'Client-Peer', 
           'client-ssl-socket-class' => 'Client-SSL-Socket-Class' 
          }, 
        'client-date' => 'Mon, 16 May 2016 16:07:07 GMT', 
        'content-type' => 'application/json', 
        'client-ssl-cert-subject' => '[REDACTED]', 
        'server' => 'Apache', 
        'client-ssl-socket-class' => 'IO::Socket::SSL' 
         }, 'HTTP::Headers'), 
     '_msg' => 'OK', 
     '_request' => bless({ 
        '_content' => '<JSON_CONTENT>', 
        '_uri' => bless(do{\(my $o = '<URL>')}, 'URI::https'), 
        '_headers' => bless({ 
            'user-agent' => 'libwww-perl/6.15', 
            'content-type' => 'application/x-www-form-urlencoded', 
            'accept' => '*/*', 
            '::std_case' => { 
             'if-ssl-cert-subject' => 'If-SSL-Cert-Subject' 
              }, 
            'authorization' => 'Basic <BASE64-ENCODED USERNAME:PASSWORD>' 
           }, 'HTTP::Headers'), 
        '_method' => 'POST', 
        '_uri_canonical' => $VAR1->{'_request'}{'_uri'} 
         }, 'HTTP::Request') 
      }, 'HTTP::Response'); 
+0

Updates zu der Frage sollten als Update auf die Frage und ** nicht als Antwort ** erfolgen. –