• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 387
  • Last Modified:

Setting Cookies - Correct Order

I need to set a Cookie from a Login Page.  I have tried the set_cookie function and on a test page, I have been able to set the cookie.  On a more involved test page it isn't getting set.  Not sure why.  I have made sure of no white space, etc.  Have looked for things that would cause output to the browser but I'm still stumped.

The process I'm using goes like this:
1.  User comes to the Home page (actually could be any page on the site).
2.  Session is Started.
3.  Code runs to check for an existing Cookie. (in a separate functions php file)
4.  If a Cookie is not found, I build one.
5.  I set the cookie using "set_cookie".

Have tried using ob_start and ob_end_flush, to surround the call to the checking function.  Doesn't work.  The page also runs javascript to build the menu which is variable based on whether the user is logged in or not..  This works fine.  I can login and the menu is set correctly.  It's just that the cookie doesn't get set.  

I need to figure out why the cookie isn't getting set.  I guess the first thing to find out is what I'm doing wrong as far as the order goes.  I am asking for the following:
What order should things occur?  (Session_start, then check for cookie, etc.)  Oh, I tried moving the session start down passed the check cookie function, but this messed up since I need Session variables set to do some stuff.  

I can provide code as needed if you need to see what's going on.

Thanks

OldHatt45
0
OldHatt45
Asked:
OldHatt45
  • 6
  • 4
  • 2
1 Solution
 
Ray PaseurCommented:
Session should always start first.  session_start() will probably set a cookie of its own, but a short-lived cookie...

I'll post my sample code for this in a moment.
0
 
Ray PaseurCommented:
Be aware that any cookie you set is NOT available to the script that set it.  The next script to load will be able to find $_COOKIE.  That means that a redirect is often used after setting a cookie.

HTH, ~Ray
// SOME COOKIE VARIABLES
$my_cookie_life = 60*60*24*7; // SEVEN DAYS IN SECONDS
$cookie_value	= 'YOUR COOKIE VALUE HERE';
 
// LOGIN SUCCESSFUL - DID CLIENT ASK US TO SET A COOKIE TO REMEMBER THE LOGIN?
if ($cFlag == '') {
	$cookie_expires	= 0; // EXPIRE AT END OF SESSION
} else {
	$cookie_expires	= time() + 6*60*60 + $my_cookie_life;  // +6 HOURS FOR GMT (SERVER IN CENTRAL TIME)
}
$cookie_value	= $cookie_value; 
$cookie_name 	= "YOUR_NAME_HERE";
$cookie_path	= '/';
$cookie_domain	= ereg_replace('^www', '', strtolower($_SERVER["HTTP_HOST"])); // STARTS WITH DOT - NO WWW, ETC.
$cookie_secure	= FALSE;
$cookie_http	= TRUE;
if (!setcookie($cookie_name, $cookie_value, $cookie_expires, $cookie_path, $cookie_domain, $cookie_secure, $cookie_http)) { /* echo "Cookie Failed"; */ }
 
// IF PASSWORD = EMAIL ADDRESS, IT IS A NEW USER -  GO TO REGISTRATION PAGE
if (trim(strtolower($eMail)) == trim(strtolower($pWord))) {
	header("Location: reg.php");
	exit;
}

Open in new window

0
 
OldHatt45Author Commented:
Ray
Here's what I've got.  It's pretty much the same thing as you described above.
I can't see what (if anything) is really different except that I've put some of your stuff in functions.

Please take a look and let me know if you see anyting I've missed.

Thanks
OldHatt45
//This is the Login Page logic.  
ob_start();
session_start(); 
include_once("BCDCMemAuthFns.php");
$cokieset = 0;
$ShowMOMenu = 0;
$failed = false;
if (check_cookies()) {
	$ShowMOMenu = 1;
	$_SESSION['ShowMOMenu'] = 1;
	header("Location: Index.php");	
	break;
}
$tdate = date("M j, Y"); 
$_SESSION['lictr'] = 0;  // A counter for recording login attempts. Max = 5
if (isset($_POST['btnsubmit'])) { // if form has been submitted
	if(!$_POST['txtloginid'] || !$_POST['txtpasswd']) {
		$limsg = "You did not Fill In a Required Entry!";
		die ;
		return 0;
		break;
	}
	if (!check_user($_POST['txtloginid'], $_POST['txtpasswd'], $_POST['chkRememberMe'])) {
		$ShowMOMenu = 0;
		$_SESSION['ShowMOMenu'] = 0;
		header("Location: Index.php");	
	} else { 
		$ShowMOMenu = 1;
		$_SESSION['ShowMOMenu'] = 1;
		header("Location: Index.php"); 
	}
} else {
	$ShowMOMenu = 0;
	$_SESSION['ShowMOMenu'] = 0;
}
ob_end_flush();
?>
<script language="javascript">
ShowMemMenu = "<?php echo $_SESSION['ShowMOMenu']; ?>";
</script> 
 
===============================================================================
 
//These functions are in the included functions, php file
function check_cookies() {
	//This function checks the Cookies and validates the cookie credentials.
	// It also sets the SESSION variables for maintaining state after credentials are validated.
	global $cokieset, $BCDCMySQL;
	$rememberme = 0;
	if(isset($_COOKIE['bcdcMO']) && !is_null($_COOKIE['bcdcMO'])) { 
		//if there is, it logs you in and directes you to the members page
		defaultsessions();  //this sets the SESSION Variables we need to a known starting value.
		if (!break_cookie($_COOKIE['bcdcMO'])) {
			// The cookie routine has found a problem so send them straight to the login form.
	  		$_SESSION['limsg'] = "Stored Credentials Do Not match, Please Login Again.";
			return 0;
			break;
		}
		$cokieset = 1;
		if ($_SESSION['remember'] == 0 ) {
			//Then we want to go to the Login Page and get out of this.
			$_SESSION['limsg'] = "Please Login.";
			$cokieset = 0;
			return 0;  //a false is returned so Show Login Form.
		}
		if (!isset($BCDCMySQL)) {  //check to see if a DB Connection is already open.  If not open it.
			connect();
		}
		if (!get_magic_quotes_gpc()) {
			$tvarusr = addslashes($_SESSION['usrname']);
		} else {
			$tvarusr = $_SESSION['usrname'];
		}
		$check = mysqli_query("SELECT * FROM account WHERE login = '$tvarusr'")or die(mysql_error());
		$check_ttl_rows = mysqli_num_rows($check);
		if ($check_ttl_rows != 1) {
	  		$_SESSION['limsg'] = "A problem has been encountered, please contact the Web Master.";
	  		defaultsessions();
			return 0;
		}
		while($info = mysqli_fetch_array( $check, MYSQLI_ASSOC )) {
			//First check to see if account is locked out.
			if ($info['locked'] <> 0) {
	  			$_SESSION['limsg'] = "Sorry, access to this account has been restricted. <br> Please contact the Web master.";
				$_SESSION['logged_in'] = 0; 
				$_SESSION['acctlocked'] = 1;
				return 0;
				break;
			}
			$accept = $info['bcdcip'];
			if (!IPCheck($accept)) {
				// If the IPCheck fails then they will need to do a Login, so we dont bother going any further.
	  			$_SESSION['limsg'] = "Sorry, Auto-Credentials Do Not Match, Please Log In.";
				$cokieset = 0;
				$_SESSION['logged_in'] = 0; 
				return 0;
				break;
			}
			if ($info['locked']) {
				$_SESSION['logged_in'] = 0; 
				$_SESSION['limsg'] = "Sorry, you need to contact the webmaster to resolve this problem";
				return 0;
				break;			
			}
			//need to do the md5 hash
			if ($_SESSION['usrpwd'] != $info['passwd']) {
				$cokieset = 0;
				$_SESSION['logged_in'] = 0; 
	  			$_SESSION['limsg'] = "Sorry, Auto-Credentials Do Not Match, Please Log In.";
				return 0;
				break;
			} else {
				$cokieset = 1;
				$_SESSION['logged_in'] = 1; 
				$lastCookie = $_COOKIE["bcdcMO"];
			    setcookie("bcdcMO", $lastCookie, time() + (86400*30));
				if ($usrremme == 1) {
					build_cookie($_SESSION['usrname'], $_SESSION['usrpwd'], $_SESSION['usrrip'], $_SESSION['remember']);
				}
				$_SESSION['limsg'] = "Automatic Login Successful.";
				return 1;
				break;
			}
		}
	} else {
		// the cookies are not set.
		// and Rememberme was not set so Show Login page/Form
		$cokieset = 0;
		$_SESSION['logged_in'] = 0; 
	  	$_SESSION['limsg'] = "Please Log In.";
		return 0;
	}
}
 
  function check_user($usrname, $usrpwd, $usrremme) {
    global $BCDCMySQL;
	if (!isset($BCDCMySQL)) {  //check to see if a DB Connection is already open.  If not open it.
		if(!connect()) {
			$_SESSION['limsg'] = "Cannot Connect to the Data Source!\n";
			break;
		}
	}
	if (!get_magic_quotes_gpc()) {
 		$usrname = addslashes($usrname);
	}
    $sql = "select * from acct where login = '$usrname'";
	$result = mysqli_query($BCDCMySQL, $sql);
	$row_result = mysqli_fetch_array($result, MYSQLI_ASSOC);
	$rsuserip = $row_result["bcdcip"];
    if (mysqli_num_rows($result) == 1) {
		//Check for Locked status.
		if ($row_result['locked']) {
			$_SESSION['limsg'] = "Sorry, you need to contact the webmaster to resolve this problem";
			$_SESSION['logged_in'] = 0;
			//echo "Row Locked";
			return 0;
			break;
		}
		//We know the ID matches so now check the password $usrpwd is the raw pw
		if (!($usrpwd == $row_result['passwd'])) {
			$_SESSION['lictr'] = $_SESSION['lictr'] + 1;
			$_SESSION['logged_in'] = 0;
			$_SESSION['limsg'] = "The ID/Password combination entered in not valid. \n Please Correct and Re-Enter.";
			//echo "PW-ID dont match";
			return 0;
			break;
		} else {	//Passwds match so, lets set the session vars and build a cookie.
			$_SESSION['logged_in'] = 1;
			$_SESSION['lictr'] = 0;
			$_SESSION['limsg'] = "Welcome, you have been Logged in and may now access the Members Only Area";
			$_SESSION['ShowMOMenu'] = 1;
			//echo "Login Successful";
				//build_cookie($usrname, $usrpwd, $_SESSION['usrrip'], $usrremme);
			//}
		}
        return 1;
    } else {
        $_SESSION['limsg'] = "Sorry, you are not authorized!";
		$_SESSION['logged_in'] = 0;
		$_SESSION['lictr'] = $_SESSION['lictr'] + 1;
		$_SESSION['ShowMOMenu'] = 1;
		//echo "Not authorized";
        return 0;
    }
}
 
 
function build_cookie($usrname, $usrpwd, $usrrip, $usrremme) {
    if ($usrremme == 1) {
		setcookie("bcdcMO","$usrname|$usrpwd|$usrrip|$usrremme",time()+ (86400*30));
		$_SESSION['remember'] = 1; 
	} else {
		$_SESSION['remember'] = 0;
	}
	return;
}
 
function break_cookie($usrcookie) {
    //global $varremme, $varpwd, $varusr, $varuip;
    //This function retrieves the values from a multi-value cookie and returns an array
	// from which we separate out the necessary variables.
    if (strlen($usrcookie) == 0) {
		$varusr = "";
		$varpwd = "";
		$varuip = "";
		$varremme = 0;
		defaultsessions();
		return 0;
	} else { 
		$data = explode("|",$usrcookie);
		$varusr = $data[0];
		$varpwd = $data[1];  
		$varuip = $data[2];
		$varremme = $data[3];
	}
	if (!get_magic_quotes_gpc()) {
    	$_SESSION['usrname'] = addslashes($varusr) ;
	}
	if (strlen($varpwd) == 32) {
		// Since this is coming from a user machine, we need to check for illegal/bad chars.
		if (!get_magic_quotes_gpc()) {
			$varpwd = addslashes($varpwd);
		}
		$_SESSION['usrpwd'] = $varpwd;
	} else {
		return 0;
	}
	if (strlen($varremme) == 1) {
	    $_SESSION['remember'] = $varremme; 
    	$_SESSION['cokieset'] = 1; 
	} else {
		$_SESSION['remember'] = 0;
    	$_SESSION['cokieset'] = 0; 
		return 0;
	}
    //$_SESSION['sessionid'] = '';
	$_SESSION['usrrip'] = $varuip;
	return 1;
}

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
scrathcyboyCommented:
You seem to be mixing cookies with sessions -- they are totally different (even if the results appear the same).  Which do you want -- PHP cookies or PHP sessions?  You don't need both, and if you want to access these with javascript, then you need CLIENT SIDE cookies, NOT PHP sessions.  So which is it?
0
 
OldHatt45Author Commented:
Well, I want to store a Cookie (multi valued) on the client machine.
I want to use PHP to access the database and what I "know how to do" is to use sessions to maintain state and variables across pages.  I have some nice code for several things (menus, etc) in javascript.

I thought I could use the 3 things to accomplish what I want.  I am however, open to suggestions and ideas.  I do want to keep my javascript menu system.  Works great. :-)  Works off a js file and I know how to move variables from php to javascript.
I do want to validate login and cookie on the server against the database.  

Those   are the things I need/want to do.  

Thanks

OldHatt45
Feel free to go from there.
0
 
scrathcyboyCommented:
Too much for a single question, about 100 pages of learning.  Ray Passeur, back to you.
0
 
Ray PaseurCommented:
Well, with 239 lines of code and not much idea about what you're trying to do, exactly, I may not be able to help very much.  But here are some ideas and resources...

Get the book, "PHP 5 in Practice" by Eli White.  It is full of examples to help with this sort of stuff.  Eli's a good guy and a developer for Digg.  Don't wait on this - call a couple of bookstores or use Amazon.com.

Isolate the problem a little more.  239 lines of code is too much to debug.  Notice that my example is only 23 lines, and that included comments and spacing for readability.

Read php.net on cookies and sessions, then read it again and look at the user-provided examples.

Some specifics (and some generalizations):

Session variables can be used to preserve state within the life of a browser instance, and usually this is a single trip to the web site.  You say session_start(), put variables into the $_SESSION array, and you can find these variables from page to page as the client navigates your web site.  The session variables are kept on the server.  Small sidebar note: If you put objects or arrays into a session variable, you should serialize() them first.

Cookie variables can be used to preserve state within the life of the cookie, which is a lifetime that ends at a date certain, or sooner if the client removes the cookie, but typically it is a long time, perhaps several days or even months.  Cookie variables are kept on the client machine, and are retrieved from the browser, and are presented to your server-side scripts in $_COOKIE, which is a superglobal array like $_SESSION.

You should keep information related to the client state in the data base, and load it into session.  You should keep a key or pointer to this client state information in the cookie.

When you set session data it is available instantly to all scripts in the site.  When you set cookie data it is only available at the time of a new page load.

Let's assume that you have a well-designed client data base.  Each user has a user_id, password and cookie_id in his personal record.  There can be lots of other information, of course, but that's not relevant for the moment.

Here is a general logic flow for login/logout with sessions and cookies (minimal security):

1. All pages EXCEPT login page: Set current $PHP_SELF in $_SESSION["page_id"].  Is there a cookie in $_COOKIE?  

1.A. If so, use its value to look up the client in the data base and populate the session variables to show the user is logged in.  

1.B. If not, or it's not in the data base, redirect to the login page.

2. Login page: Form input for credentials.  Are the user_id and password valid?

2.A. Yes, retrieve client data from the DB, set the cookie_id and other information with setcookie() and redirect to the page in $_SESSION["page_id"].

2.B. No, ask for userID and password.

3. Logout page: clear the session array, destroy the session.  Depending on the logic you want for returning clients, you might also force the cookie to expire.

If you code this correctly, you will have a local function called "access_control()" and all you will need to start your page script will be line 1 of the code snippet, and all you will need to protect a script will be line 2.

Good luck with your project, ~Ray

require_once('config.php');
access_control();
 
// REST OF SCRIPT HERE

Open in new window

0
 
OldHatt45Author Commented:
Ray,

Your last post is EXCELLENT!!!!!  Have purchsed the book you recommended already!!!
I do have a couple of questions, if you wouldn't mind, regarding your last post.

1.  You say in your item 1, to set $_SESSION['page_id'] = $PHP_SELF;
     This says to me that I need to do a session_start before doing this.  So, should the session_start be
     on line 1?  Followed immediately by the page_id set sttement?  
2.  It sounds like you are saying to store the user credentials in the database, and just have a pointer in the Cookie to that record in the database, thus not passing the ID and password across the network and also not storing this information on the users machine inside the cookie.  Is that correct??
3.  Your statement "If you code this correctly, you will have a local function called "access_control()" and all you will need to start your page script will be line 1 of the code snippet, and all you will need to protect a script will be line 2."
   a.  Calling the "require_once('config.php') is the file where you store all the "access_control" functions.  I assume this also includes setting the PHP_SELF as a session variable.  Is that correct?
  b.  The session_start comes before the require_once statement????
  c.  I don't understand the last part about protect a script on line 2.  Please explain a bit more, please.

Thanks in Advance.  Your explanation so far is EXCELLENT and EXACTLY the kind of thing I am Looking for!  based on "Give a man a fish and feed him for a day, teach him how to fish and feed him forever."
Just wish I could give you more points

OldHatt45
0
 
Ray PaseurCommented:
Yes, I have the book, right beside me right now.

Answers, as specific as I can be...
1. Yes, do session_start() on every page.  It's part of that "config.php" script that gets included at the top.  See code snippet for an excerpt from my config file.

2. Yes, exactly.

3.  The access_control function would be present in the config.php script.  (All my local functions are in there, so they are available on every page.)  The access_control() function tests to see if $_SESSION shows that the client is logged in.  If so, it returns.  If not, it loads $PHP_SELF and redirects to the login page.  On public pages, you would omit access control.  On protected pages, you only have to add one statement to obtain access control, handle login processing,. etc.
<?php // config.php
 
// DO NOT RUN THIS SCRIPT STANDALONE
if (count(get_included_files()) < 2) { header("HTTP/1.1 301 Moved Permanently"); header("Location: /"); exit; }
 
// BYPASS TWO LOCAL SERVER ISSUES
ini_set('session.bug_compat_42',0);
ini_set('session.bug_compat_warn',0);
 
// SEE ALL THE ERRORS ALL THE TIME
error_reporting(E_ALL);
 
// ALL PAGES HAVE ACCESS TO SESSION
session_start();
 
// CONSTANTS
DEFINE ("YAHOO_API", "M300zoO0nPV34GkF ... k3iEyQjT0U");
/* etc. etc. etc. */

Open in new window

0
 
Ray PaseurCommented:
An access_control() function would look something like this...

The login page simply puts up a form and checks the response against the data base.  If the credentials match, the login page loads user_key and user_cookie into $_SESSION and redirects to the calling page.  If the credentials don't match, it rewrites the request form.

HTH, ~Ray
/* ************************************************************************* */
//
// ACCESS CONTROL FUNCTION
//
function access_control($public='No') {
	global $db_connection, $my_dbt_prefix;
 
// IF SESSION HAS USER KEY, ALREADY LOGIN
	if ($_SESSION["user_key"] != '') {
		header("Cache-control: private");
return TRUE;
}
 
// IF PUBLIC PAGE, NO LOGIN NEEDED
	if (trim(strtolower($public)) == 'public') {
		header("Cache-control: private");
return TRUE;
}
 
// IF COOKIE, NO NEED TO LOGIN
	$my_user_cookie	= $_COOKIE["WWW_user"];
	if ($my_user_cookie != '') {
		$sql	= "SELECT * FROM {$my_dbt_prefix}_USERS WHERE user_cookie = \"$my_user_cookie\" LIMIT 1";
		if (!$r = mysql_query("$sql", $db_connection)) { fatal_query_error($sql); }
		$row	= mysql_fetch_assoc($r);
		$_SESSION["user_key"]	= $row["user_key"];
		$_SESSION["user_cookie"]= $row["user_cookie"];
		header("Cache-control: private");
return TRUE;
}
 
// ESTABLISH THE ENTRY/RETURN PAGE, PRESERVING GET ARGUMENTS
	if (empty($_SERVER["HTTPS"])) { $protocol = 'http://'; } else { $protocol = 'https://'; }
	$_SESSION["my_return_uri"]	= $protocol . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
 
// TRANSFER TO THE LOGIN PAGE
	$login_page = '/login.php';
	header("Location: $login_page");
	exit();
}
/* ************************************************************************* */

Open in new window

0
 
OldHatt45Author Commented:
Ray,
THANK YOU! You gave me what I needed!!!  Had to do some tweaking to make it play in my design, but  with the explanations, it was Perfect!  
Thanks Again
OldHatt45
0
 
Ray PaseurCommented:
Glad you got it moving forward!  Thanks for the points, and Happy Thanksgiving ~Ray
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now