33

If you try to login at https://orbit.theplanet.com/Login.aspx?url=/Default.aspx (use any username/password combination), you can see that the login credentials are sent as a non-traditional set of POST data: just a lonesome JSON string and no normal key=value pair.

Specifically, instead of:

username=foo&password=bar

or even something like:

json={"username":"foo","password":"bar"}

There's simply:

{"username":"foo","password":"bar"}

Is it possible to perform such a request with LWP or an alternative module? I am prepared to do so with IO::Socket but would prefer something more high-level if available.

Richard Simões
  • 12,401
  • 6
  • 41
  • 50

4 Answers4

79

You'll need to construct the HTTP request manually and pass that to LWP. Something like the following should do it:

my $uri = 'https://orbit.theplanet.com/Login.aspx?url=/Default.aspx';
my $json = '{"username":"foo","password":"bar"}';
my $req = HTTP::Request->new( 'POST', $uri );
$req->header( 'Content-Type' => 'application/json' );
$req->content( $json );

Then you can execute the request with LWP:

my $lwp = LWP::UserAgent->new;
$lwp->request( $req );
friedo
  • 65,762
  • 16
  • 114
  • 184
  • My search leading to this was using the vanilla GET/POST method , and it might not be obvious from the json snippet, so I dare to contribute also the GET/POST usage `new HTTP::Request( 'GET' => "http://url/path", ['Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'], 'par1=par1value&par2=par2value' );` – FantomX1 Mar 16 '21 at 09:50
16

Just create a POST request with that as the body, and give it to LWP.

my $req = HTTP::Request->new(POST => $url);
$req->content_type('application/json');
$req->content($json);

my $ua = LWP::UserAgent->new; # You might want some options here
my $res = $ua->request($req);
# $res is an HTTP::Response, see the usual LWP docs.
hobbs
  • 223,387
  • 19
  • 210
  • 288
14

The page is just using an "anonymized" (without name) input, which happens to be in JSON format.

You should be able to use $ua->post($url, ..., Content => $content), which in turn use the POST() function from HTTP::Request::Common.

use LWP::UserAgent;

my $url = 'https://orbit.theplanet.com/Login.aspx?url=/Default.aspx';
my $json = '{"username": "foo", "password": "bar"}';

my $ua = new LWP::UserAgent();
$response = $ua->post($url, Content => $json);

if ( $response->is_success() ) {
    print("SUCCESSFUL LOGIN!\n");
}
else {
    print("ERROR: " . $response->status_line());
}

Alternatively, you can also use an hash for the JSON input:

use JSON::XS qw(encode_json);

...

my %json;
$json{username} = "foo";
$json{password} = "bar";

...

$response = $ua->post($url, Content => encode_json(\%json));
Paolo Rovelli
  • 9,396
  • 2
  • 58
  • 37
  • 1
    I believe you are missing the content-type setting for the "post" function - I don't think LWP guesses it and it defaults to 'x-www-form-urlencoded' – Noam Rathaus Apr 02 '19 at 10:33
1

If you really want to use WWW::Mechanize you can set the header 'content-type' before post

$mech->add_header( 
'content-type' => 'application/json'
);

$mech->post($uri, Content => $json);
TheDrev
  • 469
  • 2
  • 7
  • 16