Asked  7 Months ago    Answers:  5   Viewed   36 times

I am working on a project for a client which needs an automatic login from a link click.

I'm using a handshake page to do this with the following code:

$username = "admin";
$password = "blog";
$url = "http://wordpressblogURL/";
$cookie = "cookie.txt";

$postdata = "log=" . $username . "&pwd=" . $password . "&wp-submit=Log%20In&redirect_to=" . $url . "blog/wordpress/wp-admin/&testcookie=1";
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url . "blog/wordpress/wp-login.php");

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
curl_setopt ($ch, CURLOPT_TIMEOUT, 60);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt ($ch, CURLOPT_REFERER, $url . "blog/wordpress/wp-login.php");

curl_setopt ($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt ($ch, CURLOPT_POST, 1);
$result = curl_exec ($ch);
curl_close($ch);
echo $result;

exit;

This works fine. It logs me in great.

The problem is that I believe WordPress keys off of the URL.

To elaborate, my handshake page (which logs me in) is in the "blog" directory and my WordPress application is in the "wordpress" directory which sits inside the "blog" directory. The URL in the browser says ..blog/handshake.php. However, it has the Admin section of WordPress in the browser window. WordPress Admin links now do not function correctly, because the URL is in the ../blog directory when it needs to be in the ..blog/wordpress/wp-admin directory.

Is there a way in cURL to make it so that the URL in the browser reflects the actual page?

Should I be using FSockOPen instead?

 Answers

12

Kalium got this right -- paths in the WordPress interface are relative, causing the administration interface to not work properly when accessed in this manner.

Your approach is concerning in a few ways, so I'd like to make a few quick recommendations.

Firstly, I would try to find a way to remove the $username and $password variables from being hard-coded. Think about how easy this is to break -- if the password is updated via the administration interface, for instance, the hard-coded value in your code will no longer be correct, and your "auto-login" will now fail. Furthermore, if someone somehow comprises the site and gains access to handshake.php -- well, now they've got the username and password for your blog.

It looks like your WordPress installation rests on the same server as the handshake script you've written, given the path to /blog is relative (in your sample code). Accordingly, I'd suggest trying to mimic the session they validate against in your parent applications login. I've done this several times in the past -- just can't recall the specifics. So, for instance, your login script would not only set your login credentials, but also set the session keys required for WordPress authentication.

This process will involve digging through a lot of WordPress's code, but thats the beauty of open source! Instead of using cURL and hard-coding values, try to simply integrate WordPress's authentication mechanism into your application's login mechanism. I'd start by looking at the source for wp-login.php and going from there.

If all else fails and you're determined to not try to mesh your session authentication mechanism with that of WordPress, then you could immediately fix your problem (without fixing the more concerning aspects of your approach) with these changes to your code:

First, add the following curl_opt:

curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);  // Enables session support

Then, add this after closing the cURL handler:

curl_close($ch);
// Instead of echoing the result, redirect to the administration interface, now that the valid, authenticated session has been established
header('location: blog/wordpress/wp-admin/');
die();

So, in this less than ideal solution you'd use cURL to authenticate the user, and then rather than attempt to hijack the administration interface into that current page, redirect them to the regular administration interface.

I hope this helps! Let me know if you need more help / the solution isn't clear.

Wednesday, March 31, 2021
 
Palladium
answered 7 Months ago
89

OK, after a bit of debugging, I believe the issue is the default User-Agent string Wordpress sets in wp-includes/class-http.php, set when creating an http request for wp_remote_get().

The option has a filter, but the default is created like so:

'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ),

So in my case, the 'user-agent' header value was: "Wordpress/4.3.1; http://myurl.com"

When I hook into the filter http_headers_useragent and return an empty string, or even a different user-agent string such as: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8) AppleWebKit/535.6.2 (KHTML, like Gecko) Version/5.2 Safari/535.6.2', the request will return a successful 200 response.

Not sure if the semicolon is the true culprit, but if I remove it and set the user-agent string to just "Wordpress/4.3.1", the request is successful as well.

Saturday, May 29, 2021
 
tpow
answered 5 Months ago
77

should these variables be different?

//                                              v
curl_setopt($ch1, CURLOPT_COOKIEFILE, $cookie_fie_path);
curl_setopt($ch1, CURLOPT_COOKIEJAR,  $cookie_file_path);
//                                              ^

It may be that your cookies aren't being stored/retrieved properly.

httpRequest Class Example (short form static constructors):

$loginAttempt = httpRequest::post(
        'https://kinray.com/redirector1/weblink.jsp',
        'custId=XXXXX&passWord=YYYYY'
    )
    ->ignoreSSL()
    ->setCookieJar($cookie_file_path)
    ->retrieveHeader()
    ->setManualOption(CURLOPT_REFERER, "http://www.google.com")
    ->splode(); // executes the request
// you can get to the returned value with $loginAttempt->responseRaw,
// or a host of other options, see __get()

$loggedInPage = httpRequest::get('https://kinray.com/weblink2/search/categories.do?scrollType=&code=&alwaysCustomerNumber=023987')
    ->ignoreSSL()
    ->setCookieJar($cookie_file_path)
    ->splode();

you can easily get to the response body by accessing the body property ($loggedInPage->body, for example) from there. Let me know if this works for you.

EDIT: Sample Response

<script>document.oncontextmenu = function(){return false;};</script>
<!--categories.jsp-->
<html>
<head>
<title></title>
<LINK rel=stylesheet type=text/css href="/weblink2/styles.css">
<script>
   
   
   
















top.frames.search.setPaging('up'  , true);
top.frames.search.setPaging('down', true);


   var categories  = [ 
   
   ["27","BABY DIAPERS                                      "],
   
   ["28","BABY FORMULA                                      "],
   
   ["66","BAG STUFFER (PG)                                  "],
   
   ["90","BAG STUFFER FLYER DECEMBER                        "],
   
   ["89","BAG STUFFER FLYER NOVEMBER                        "],
   
   ["78","BAG STUFFER WINDOW SIGNS DECEMBER                 "],
   
   ["77","BAG STUFFER WINDOW SIGNS NOVEMBER                 "],
   
   ["35","BATTERIES                                         "],
   
   ["17","BONUS , VALUE PACKS                               "],
   
   ["22","CANDY AND GUM                                     "],
   
   ["49","CANDY AND GUM - SUGARFREE                         "],
   
   ["25","COSMETICS                                         "],
   
   ["52","COUGH &amp; COLD LIQUIDS                              "],
   
   ["21","DIABETIC NEEDS                                    "],
   
   ["42","DIAGNOSTICS                                       "],
   
   ["16","DISPLAYS, FLOORSTANDS                             "],
   
   ["33","ELECTRONICS                                       "],
   
   ["43","ETHNIC                                            "],
   
   ["26","FAMILY PLANNING                                   "],
   
   ["44","FILM, CAMERAS, &amp; VIDEO                            "],
   
   ["32","FOOD ITEMS                                        "],
   
   ["5","FRAGRANCES MEN                                    "],
   
   ["45","FRAGRANCES WOMEN                                  "],
   
   ["54","GENERIC ANTIBIOTICS                               "],
   
   ["13","GENERIC SPECIALS                                  "],
   
   ["53","GENERIC TOPICALS                                  "],
   
   ["8","GENERICS NEW                                      "],
   
   ["7","HBA&#039;S NEW                                         "],
   
   ["41","HOME APPLIANCES                                   "],
   
   ["3","HOME HEALTH CARE                                  "],
   
   ["14","HOME HEALTH CARE (NEW)                            "],
   
   ["4","HOME HEALTH CARE MONTHLY SPECIALS                 "],
   
   ["93","HOME HEALTH CARE TOP 40                           "],
   
   ["36","HOMEOPATHIC                                       "],
   
   ["31","HOUSEHOLD GOODS                                   "],
   
   ["9","INJECTABLES                                       "],
   
   ["29","INSULIN                                           "],
   
   ["50","NEVER OUT OF STOCK ITEMS                          "],
   
   ["30","NUTRITIONALS                                      "],
   
   ["56","OTC PRODUCTS CONTAINING PSE                       "],
   
   ["46","PERSONAL CARE APPLIANCES                          "],
   
   ["51","PET SUPPLIES                                      "],
   
   ["59","PHARMACY FIRST                                    "],
   
   ["40","PHARMACY SUPPLIES (MISC)                          "],
   
   ["55","PRE-BOOK ITEMS                                    "],
   
   ["20","PREFERRED PLUS (KPP) NEW                          "],
   
   ["2","PREFERRED PLUS (P/L) KPP                          "],
   
   ["10","RX BAGS (PHARMACY SUPPLIES)                       "],
   
   ["12","RX SPECIALS                                       "],
   
   ["6","RX&#039;S NEW                                          "],
   
   ["24","SCHOOL SUPPLIES                                   "],
   
   ["15","SUMMER                                            "],
   
   ["60","SUNGLASSES/EYEGLASSES                             "],
   
   ["47","SYRINGES, NEEDLES, ACCESSORIES                    "],
   
   ["34","TOYS &amp; GAMES                                      "],
   
   ["18","TRIAL &amp; TRAVEL SIZES                              "],
   
   ["39","VIALS &amp; BOTTLES (PHARMACY SUPPLIES)               "],
   
   ["23","VITAMINS                                          "],
   
   ["37","WETS &amp; DRYS                                       "],
   
   ["",""]
   
   ];
   
   var titleSearch='';

   function DisplayCategories (table) {
      document.write("<TABLE class=searchTable border =0  cellPadding=0 cellSpacing=0 >");
      var k=0;
      for(var x=0; x<=(table.length-1); x++) {
         if(x%20==0)
            document.write("<TD>");
         document.write("<a href ="javascript:parent.parent.frames.search.loadCategory(categories["+x+"][0], categories["+x+"][1])">",table[x][1],"</a><BR>");
      }
      document.write("</TABLE>");
   }
   
   DisplayCategories(categories);
   top.setKeyHandlers(document);
</script>
</head>
<body>
</BODY>
</HTML>
    
Saturday, May 29, 2021
 
Extrakun
answered 5 Months ago
40

I ended up making these requests through the browser. Browsers keep HTTP(S) connections open when the server tells them to.

Alas, this solution entails some disadvantages:

  • authentication is more difficult
  • more load on the server as more connections have to be maintained
  • the solution needs additional JavaScript

But requests are much faster (about 3x) and load on the server where WordPress is running is minimized.

Saturday, May 29, 2021
 
nighter
answered 5 Months ago
73

Your code looks clean to me, unless you didn't make any mistake elsewhere. Just one thing you need to fix:

'ctl00$txtUsername' => 'xxx',
'ctl00$txtPassword' => 'xxx',

You are using %24 inside the keys, which further urlencoded by the function http_build_query()

Saturday, May 29, 2021
 
yosemite
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :