Here is my dilemma...
I basically have a script which by means of CURL posts to a 3rd party website to perform a login and then makes another post to update a users details based on that login session. Now as my site is getting busy I have multiple users doing the same thing and it seems that on occasion curl is getting confused and updating one users details with a different users information. This is causing real problems.
It seems to be that the cookie which is being used by a user after one login is being shared by other users and they end up logging in with the same cookie - confusing the 3rd party system. My code is posted below and I need to use the cookiefile and cookiejar to maintain the php session to allow me to do what I need to do. But it seems like the same cookie is being reused by all users....
Does that make sense? Is there anything I can do to change this? Please advise....
Thanks so much!
Below is the code i use to both login and post the user update
function hitForm($postURL, $postFields, $referer="", $showerr = FALSE, $ispost = TRUE) {
global $islocal, $path_escape;
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt");
curl_setopt($ch, CURLOPT_URL, $postURL);
if ($ispost)
curl_setopt($ch, CURLOPT_POST, 1);
else
curl_setopt($ch, CURLOPT_HTTPGET, 1);
curl_setopt($ch, CURLOPT_REFERER, $referer);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$ret = curl_exec($ch);
if ($error = curl_error($ch)) {
if ($showerr)
echo 'ERROR: ' . $error;
return -1;
exit;
}
$CU_header = curl_getinfo($ch);
$CU_header["err"] = curl_errno($ch);
$CU_header["errmsg"] = curl_error($ch);
curl_close($ch);
$returnout = $ret;
//for debugging purposes for now we are logging all form posts
SaveLog("hitform", "F[".$this->curruserid." - ".$this->currfunc." - ".date("d-m-y h:i:s")."]".$postFields);
return $ret;
}
You're using the same cookies.txt file for each session, so that's where the shared cookie problem is coming from. You'd need to specify a seperate file for each parallel session you want to run.
You are using a shared cookie jar for all users. Each user needs a separate cookie jar.
You need to use different cookie files for each user.
I assume your postFields includes some unique identifier for each user (like a user id, or a username), so try something like:
$cookie_file = 'cookies_' . $postFields['user_id'] . '.txt';
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
As far as I understand the problem, your script is getting wrong user information. How do you store user info anyway?
I'd say that's the source of the problem - you don't assign a unique identifier to user info, and that's where it gets nasty ;)
So, first of all, I'd associate session id with user information (or let's say, store user information in session, which is unique for everyone), and load it from there. And I guess it should do the trick ;)
Related
I am trying to create a portal such that users use SSO to access all services in the company I work for.
My goal is for the users to log in to my portal, then they will be automatically logged in to all the websites of our company and they will only need to click the icon of the website to access it without the need to enter their credentials every time, we are using Active Directory for authentication in all these websites.
I inspected the login form for each website and got the URLs of the login scripts along with the variable names of the username and password fields, then I tried to send POST requests to those scripts using cURL in PHP with the credentials in the "CURLOPT_POSTFIELDS" option.
$cookie_file_path = getcwd() . '/cookie.txt';
$agent = $_SERVER['HTTP_USER_AGENT'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://example.com/login.php');
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
$loginpage_html = curl_exec ($ch);
curl_close ($ch);
$CREDENTIALS = "username=test&password=test";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://example.com/login.php');
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$CREDENTIALS);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_REFERER, 'http://example.com/login.php');
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
$logon_result = curl_exec ($ch);
echo $logon_result;
Current output:
Users are automatically logged in to all the websites when they login to my portal, but when trying to navigate it looks like they haven't logged in in the first place as if the session is destroyed even though it first shows that you're logged in.
Expected output:
Users are automatically logged in to all the websites when they login to my portal and can access those websites as if they are normally logged in.
And as a beginner, I want to ask is this actually a good way to achieve SSO in PHP and Active Directory or is there a better way to do this.
Thank you.
I think your code is failing to log in users because the session cookies aren't being saved to the clients web browser. For security reasons your site won't be able to create a cookie for another website. Since your users don't have the session cookie for the target site they will be treated like a new user.
A more common way to achieve a single sign experience would be to use SAML. Since you mentioned your company used Active Directory you can use ADFS as the Identity Provider. Some of your enterprise applications may already support SAML authentication.
I'm trying to use cURL to login to a website, but it doesn't seem to be working. I started by testing it on my own site which works, but when I try on the site that I actually need it wont login, and just gets the login page.
$loginUrl = 'https://www.ekomi.co.uk/login.php';
$postData = 'login_email=-----&login_passwort=-----';
$ch = curl_init();
$agent = $_SERVER['HTTP_USER_AGENT'];
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_URL, $loginUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies/cookies.txt');
$postResult = curl_exec($ch);
print_r($postResult);
It does give an error that $_SERVER index is undefined, but it still allowed me to login to my site, also I am assuming that the $postData should be the names of the user and password fields.
Is there anything wrong with the script that could be the problem, or could it maybe be the way which the site logs in?
Edit
The problem seems to be because of the # symbol in the login email, I've tried putting %40 as suggested in other questions but this doesn't work.
First thing you must navigate to the page and get the csrf (Cross-site request forgery-basically it checks that the login form is seen by the user, sets a random hash in the session and checks if you give it back) and then make the post.
Hello i have a problem trying to store cookies in a txt file.
my_cookies.txt is a txt in the same folder of this file.
I want to manage cookie before and after login, in this example facebook
Then i want to insert that cookie in a database but first i need to put it in a .txt or atleast save
Obviously email and password dont be those. =)
<?php
/* STEP 2. define path of form_action */
$url = "https://facebook.com/login.php?login_attempt=1";
$email = "nn";
$password = "nn";
/* STEP 3. create a connection with curl, give post information and save cookies */
$handler = curl_init();
//insert in the handler the path
curl_setopt($handler, CURLOPT_URL, $url);
//insert in the handler parameters of post
curl_setopt($handler, CURLOPT_POSTFIELDS,'email='.urlencode($email).'&pass='.urlencode($password));
//insert in the handler option to allow sending post information
curl_setopt($handler, CURLOPT_POST,1);
curl_setopt($handler, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($handler, CURLOPT_SSL_VERIFYPEER, false);
//load and save cookies generates in temp file
curl_setopt($handler, CURLOPT_COOKIEJAR, "my_cookies.txt");
curl_setopt($handler, CURLOPT_COOKIEFILE, "my_cookies.txt");
//catch information
curl_setopt ($handler, CURLOPT_RETURNTRANSFER, true);
//define agent
curl_setopt($handler, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0");
$response = curl_exec ($handler);
curl_close($handler);
echo $response;
?>
Thanks for your help =) and i hope that you can do anything to help me :(
facebook provide an API which is much less error prone than using curl to random facebook pages
To answer your actual question though this is the function you are looking for
it reads the file in to a variable which you can then store
PHP 5.3+
curl_setopt($handler, CURLOPT_COOKIEJAR, __DIR__."/my_cookies.txt");
curl_setopt($handler, CURLOPT_COOKIEFILE, __DIR__."/my_cookies.txt");
PHP 5.2-
curl_setopt($handler, CURLOPT_COOKIEJAR, dirname(__FILE__)."/my_cookies.txt");
curl_setopt($handler, CURLOPT_COOKIEFILE, dirname(__FILE__)."/my_cookies.txt");
Also use absolute paths for files. __DIR__ gives you that power!
You can assign cookies to a $cookies variable and use that in place,
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
and then after cookies' work is done in cURL process. you can do whatever you want to that variable($cookies).
TIP:
For storing into .txt - you __FILE__ to store same directory or append __FILE__ with more path to store in another directory.
You can use md5($_SERVER['REMOTE_ADDR']) for generating Separate use .txt
For storing into Database, INSERT command will be okay.
I've got NTLM (Active Directory) based service, and I need to write a PHP application. Normally, users are logging in to website with Activre Directory credentials, and it's ok.
But what I want to do, is to let them type in their credentials to PHP-written site, which in next step will use cURL to authenticate users to that Active Directory based site where they normally log in.
And this part is hard. I need then to keep session of users that through PHP cURL script authenticated to Active Directory based site in order to use them again later
(CRON querying site to determine that it has changed and automatically do some operations when this happens, which normally user has do manually).
In order to NOT store their credentials to authenticate again when this change happens, I somehow need to store NTLM session in PHP cURL site to every user that authenticated to
that site through this PHP cURL site.
My question is: Is that even possible?
Thanks in advance.
#Willem Mulder
The code you've posted actually does cookie-storing, but that is not my point becouse I've already done that (sorry for not writing it before). What I got so far is:
$cookie_file_path = dirname(__FILE__) . '/cookies.txt';
$ch = curl_init();
//==========================================================================
curl_setopt($ch, CURLOPT_USERPWD, $username. ':' . $password);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_FAILONERROR, 0);
curl_setopt($ch, CURLOPT_MAXREDIRS, 100);
//==========================================================================
$ret = curl_exec($ch);
By using options CURLOPT_COOKIEFILE and CURLOPT_COOKIEJAR, cURL does the cookie storing in local file "cookies.txt". The problem is, that when I comment CURLOPT_USERPWD option (after authenticating and storing cookie, so theoretically I have session), I cannot authorize to website. Perhaps it reinitializes NTLM Handshake authorisation and is expecting username and password, which I don't want to store.
I want to store session info only, to provide service this session info and omit second authentication, but cURL seems to not take this data from cookie file, and REWRITES it with not relevant data send to me from service as response to NOT AUTHRORISED access request.
Well, yes you could
$ch = curl_init('http://www.google.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Get headers too with this line
curl_setopt($ch, CURLOPT_HEADER, 1);
$result = curl_exec($ch);
// Get cookie
preg_match('/^Set-Cookie:\s*([^;]*)/mi', $result, $m);
var_dump(parse_url($m[1]));
// And then of course store it somewhere :-)
As seen here how to get the cookies from a php curl into a variable
I am Trying to login to 2shared with curl-php but for some reason it just returns me login page and does not set proper cookies in cookie file. Below is my code. Thanks for any help.
$user = "";
$pass = "";
$cookie = "cookie.txt";
$jsonp = 'jsonp'.time();
if (file_exists($cookie)) {
unlink($cookie);
}
$post = array(
"login" => $user,
"password" => $pass,
"callback" => $jsonp
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.2shared.com/login?callback=".$jsonp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-Requested-With: XMLHttpRequest'));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_REFERER, 'http://www.2shared.com/');
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20100101 Firefox/12.0");
curl_setopt($ch, CURLOPT_ENCODING, "UTF-8" );
$return = curl_exec($ch);
curl_close($ch);
echo $return;
EDIT:
When I login via browser and watch traffic via HTTP analyzer i noticed after hitting login button it returns this data and redirect to loginRedirect object and i notice it set some cookies which does not appears while I am doing php-curl request:
{
"ok":true,
"rejectReason":"",
"loginRedirect":"http://www.2shared.com/account/homeDoorway.jsp;jsessionid=3F253C7C641C7A8402D4AC9872C1CEAE.dc282?rand=0.8112776952920494",
"loggedIn":"myemail#email.com",
"needActivation":false
}
But when trying to login with curl-php above code it return me this data:
jsonp1339804887({
"ok":true,
"rejectReason":"",
"loginRedirect":"http://www.2shared.com/login.jsp?sessionUnavailable=1",
"loggedIn":"",
"needActivation":false
})
As always when doing web scraping, the key is to compare with a recorded session done manually with a browser (like with LiveHTTPHeaders or similar tools). Then make sure that your script is sending a request as similar as the recorded one as possible.
If you had done that, you would've seen that...
The login form on 2shared doesn't seem to use a multipart formpost, so your passing of $array to CURLOPT_POSTFIELDS is wrong. It should simply be a string in the form of "login=$name&password=$secret". This said, this may not be the only flaw in your approach.
This may be just a short in the dark, but it appears to me that you actually should look at the redirect and follow it. The error message does indicate that you're not actually within a functioning session on the server side – and the session identification is part of the address that you would have been redirected to but chose not to follow. ;jsessionid=3F253C7C641C7A8402D4AC9872C1CEAE.dc282 The latter part ?rand=0.8112776952920494 appears – to me! – to be a random number the system also wants to have sent back. I'll take this to be a trivial token mechanism to make sure that the request actually is fresh and not something like a script that tries to get in :-)
Also, are you certain that the callback mechanism you use (with time) does make so much sense?
Have you tried to get to the login page innocently, watching for the redirect to pop up and then start your other code from there?