Click to See Complete Forum and Search --> : Login Processing Doesn't Seem to Process


Joseph Witchard
09-03-2008, 04:09 PM
Form Processing:
<?php

// include the connection settings



define('DB_HOST', 'host');
define('DB_USER', 'user');
define('DB_PWD', 'password');
define('DB_NAME', 'database');

// connect to the database

$conn = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);

// process the form

if (array_key_exists('login', $_POST) && !empty($_POST['login'])) {



// create an empty array for missing fields

$missing = array();

/* here, I'm going to create an
array to hold the form fields.
if the form fields are empty,
I'll add them to the $missing
array. */

$fields = array("F_Username" => $_POST['username'], "F_Pwd" => $_POST['pwd']);

foreach($fields as $field => $value) {

if (empty($field)) {

array_push($missing, $field);

}

}



// if $missing is empty, continue the processing

if (empty($missing)) {

// assign the form fields to variables

$username = $fields["F_Username"];
$pwd = $fields["F_Pwd"];

// clean up the input


$username = htmlentities($username, ENT_QUOTES, 'UTF-8');
$pwd = htmlentities($pwd, ENT_QUOTES, 'UTF-8');

$query = "SELECT user_id, username, pwd FROM users WHERE username='$username' AND pwd ='$pwd'";



// prepare the statement

if ($stmt = $conn->prepare($query)) {


// execute

$stmt->execute();

$stmt->store_result();

if ($stmt->num_rows < 3) {

exit;

}

// bind the result

$stmt->bind_result($user_ID1, $username1, $pwd1);

// store the result











// fetch the values

while ($stmt->fetch()) {



session_set_cookie_params(900);

session_start();

$_SESSION['id'] = $user_ID1;
$_SESSION['username'] = $username1;
$_SESSION['pwd'] = $pwd1;

header("Location: http://uhrebirth.com/staff/admin_center.php");


}












// close the statement

$stmt->close();

// close the connection

$conn->close();



}

}

}



?>

HTML Form:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>

<title>Rebirth Test Page</title>

<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="cache-control" content="no-cache">

<link href="/css/general.css" rel="stylesheet" type="text/css">

</head>

<body>

<div align="center">

<form id="AdminLogIn" name="AdminLogIn" method="post" action="/staff/admin_process.php">

<input type="text" id="username" name="username"><br>
<label for="username">Username</label><br>
<input type="password" id="pwd" name="pwd"><br>
<label for="password">Password</label>

<br><br>

<input type="submit" id="login" name="login" value="Login">
<input type="reset" value="Reset"><br><br>

</form>

</div>

</body>

</html>



Every time I submit the form, I get taken to the processing page, which does nothing more than display a blank white window in my browser. It's like it doesn't even attempt to send me to the Admin Page, and it's like the processing page doesn't process anything at all. I would think that maybe it's because the action attribute sends it to an external page instead of submitting the form to its page with PHP included above the doctype (I've always had trouble with the former, for some reason), but it does the same thing either way. Can I get some help?

SyCo
09-03-2008, 05:46 PM
You've got your header() redirect set inside a while loop. It's probable the condition is not met. You can only redirect once so wouldn't an if() be more appropriate?

De-bug by echoing something to the page where the header is and comment the header redirect out. If you don't see your debug output you're not entering the while loop so not hitting the redirect.

SyCo
09-03-2008, 05:49 PM
Oh, also when setting SESSION you might want to give them a sub array. When you add things to the session you might not always require them to be logged in to use the values, so
$_SESSION['login']['id']
$_SESSION['login']['un']
$_SESSION['login']['pw']

can all be unset with
unset($_SESSION['login']);
leaving all other session vars unaffected.

Joseph Witchard
09-03-2008, 08:21 PM
Okay, I've done some debugging. After I got through testing the script I have confirmed that the execution, storing result, and binding the result were all successful. However, for some reason, the while loop never gets entered. I don't understand what I'm doing wrong; I've been following the examples from the PHP website to the dot, but what their examples say to do doesn't seem to work.

Any ideas?

**EDIT: I just tried submitting the form. It does say after the form is submitted that the While Loop was entered. However, I'm still not getting redirected anywhere.

NogDog
09-03-2008, 09:50 PM
I think there's a logic error here:

if ($stmt->num_rows < 3)

Theoretically you should only receive one of two results for num_rows: 0 or 1. Therefore that if condition should always fail. Perhaps you are confusing result rows with the number of columns (fields) in each result row?

PS: You probably do not need to do the store_result() call, but if you do, make sure you do a free_result() before you leave the login processing.

Oh, one more thing, as you should only receive 0 or 1 result rows, you don't need to do a while loop. Just see if you got exactly one result row, and if so, fetch it.

Joseph Witchard
09-03-2008, 10:18 PM
That's what I was doing: trying to get each field. If that's not what $stmt->num_rows() does, then what does it do?

Joseph Witchard
09-03-2008, 10:56 PM
Could someone give me an example of how they would write out fetching the database fields, assigning them to the session variables, and then redirecting the user? I've been working on this since last night, and I can't figure out what I'm doing wrong. Even when I make every fix that has been suggested here, it still doesn't work:confused:

P.S. If at all possible, please use mysqli in your examples.

NogDog
09-03-2008, 11:42 PM
This should be closer, but of course it's untested:

<?php
// include the connection settings
define('DB_HOST', 'host');
define('DB_USER', 'user');
define('DB_PWD', 'password');
define('DB_NAME', 'database');
// connect to the database
$conn = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME);
// process the form
if (array_key_exists('login', $_POST) && ! empty($_POST['login']))
{
// create an empty array for missing fields
$missing = array ();
/* here, I'm going to create an
array to hold the form fields.
if the form fields are empty,
I'll add them to the $missing
array. */
$fields = array ("F_Username"=>$_POST['username'], "F_Pwd"=>$_POST['pwd']);
foreach ($fields as $field=>$value)
{
if ( empty($field))
{
array_push($missing, $field);
}
}
// if $missing is empty, continue the processing
if (empty($missing))
{
// assign the form fields to variables
$username = $fields["F_Username"];
$pwd = $fields["F_Pwd"];
// clean up the input
$username = htmlentities($username, ENT_QUOTES, 'UTF-8');
$pwd = htmlentities($pwd, ENT_QUOTES, 'UTF-8');
$query = "SELECT user_id, username FROM users WHERE username='$username' AND pwd ='$pwd'";
// prepare the statement
if ($stmt = $conn->prepare($query))
{
// execute
$stmt->execute();
// $stmt->store_result();
if ($stmt->num_rows == 1)
{
session_set_cookie_params(900);
session_start();
// bind the result
$stmt->bind_result($_SESSION['id'], $_SESSION['username']);
// fetch the values
$stmt->fetch();
header("Location: http://uhrebirth.com/staff/admin_center.php");
}
else
{
// edit for whatever you want to happen on invalid login:
die("Invalid login");
}
// close the statement
$stmt->close();
// close the connection
$conn->close();
}
}
}
?>

Joseph Witchard
09-04-2008, 05:08 AM
Thanks:) I'll test that out as soon as I can get a moment.

What would I use to count the number of fields that were selected from the database if you don't use mysqli->num_rows for that? I was planning on using that to see if the password supplied by the user matched up with one in the database, or else didn't exist in the database.

NogDog
09-04-2008, 05:20 AM
That's what the "where" clause in your query is already doing. Therefore if it returns 1 row, then you've found a matching username/password pair, so you're good to go.

. . .WHERE username='$username' AND pwd ='$pwd'";

Joseph Witchard
09-04-2008, 03:34 PM
SELECT employees.Fisrtname, employees.Lastname, crew.experience FROM
employees, crew;


What about a query like that? How would you check then?

Also, I don't understand something in the script you posted. In what you posted, why was it even necessary to use $stmt->fetch()? I thought that the whole point of that was to pull information out of the database, but it doesn't appear as though that's what you're using it for (I may be wrong, though).

NogDog
09-04-2008, 04:37 PM
SELECT employees.Fisrtname, employees.Lastname, crew.experience FROM
employees, crew;


What about a query like that? How would you check then?

Well, I wouldn't use a query like that to validate a login; it would need to include password validation as part of it.
Also, I don't understand something in the script you posted. In what you posted, why was it even necessary to use $stmt->fetch()? I thought that the whole point of that was to pull information out of the database, but it doesn't appear as though that's what you're using it for (I may be wrong, though).
The "bind" command before it simply tells PHP which variables are to hold the values returned by a fetch. You then have to do the fetch to actually read a row from the query result set, which will then assign the result values to the bound variables. (Since there should only be one result row, the script just does one fetch, rather than using it in a while loop as you would for queries which may return multiple rows.

Joseph Witchard
09-04-2008, 04:45 PM
What exactly is considered a row? I always get confused about that when dealing with SQL.

NogDog
09-04-2008, 06:01 PM
Suppose you do this query in a hypothetical DB:

SELECT first_name, last_name FROM users

It would return one result row for each row (i.e. each user) in that table, e.g.

Charles | Reace
Joseph | Witchard
John | Doe

So if you did something like $stmt->bind_result($first, $last), then the first time you called $stmt-fetch(), it would read the first result row, and $first would be set to "Charles" and $last would be set to "Reace". That call to fetch() also moves the "result row pointer" to the next row, so if you call fetch() again (as you might in a while loop), then on the second call the value of $first would be "Joseph" and $last would be "Witchard". So each fetch() call reads just one result "row". The values of $fist and $last would then represent the "columns" (also referred to as "fields") for that row.

Joseph Witchard
09-04-2008, 10:06 PM
Will the row always be equal to either 0 or 1, in any type of query?

NogDog
09-04-2008, 10:25 PM
Will the row always be equal to either 0 or 1, in any type of query?
The number of rows will be 0 to any positive integer, depending on the query. In the case of a login system like this where you are checking to see if a particular username exists and if the correct password was supplied for it, it should only ever return either 0 or 1 row, as the username field should have a unique index on it so that there can only ever possibly be one match for it. (If you did not force it to be unique, and two different people decided to use the same user name and also coincidentally decided to use the same password, how would you know which was which?)

Joseph Witchard
09-04-2008, 10:36 PM
Okay. I think I get it now.

I tried your edits, and it still doesn't work:( If I submit the form page to itself, it just reloads the page. If I move the processing script to an external PHP file, it just sends me to a blank white page.

Joseph Witchard
09-07-2008, 09:38 PM
UPDATE ON THIS ISSUE

Okay, I've got the SQL all set right now. Everything in that process is working perfectly. However, there is a new problem. My Admin page keeps redirecting me to the error page because for some reason, it's not able to tell that my session variables are set (and I tested them; they are indeed set). I don't understand why it's doing it, but it is. The script in my Admin page is:

<?php // check to see if the session is set

if (!isset($_SESSION['id']) || !isset($_SESSION['username']) || empty($_SESSION)) {

// send them to the error page
header("Location: http://www.uhrebirth.com/test/permission_error.php");

exit;

}

else {

session_set_cookie_params(900);
session_start();




require_once("../admin_logout.php");

}

?>

Could someone give me a hand?