I am trying to run a function that checks a db table for a username and an email. I call the function with two parameters ($user_username, $user_password). The function checks the database to see if those values exist. However, I cannot get the variables from the function to return properly. Here's what i have so far:
Function:
class registerClass{
public function checkUser($user_username, $user_email){
//connect to db via pdo...
$st_1 = $handler->prepare("SELECT * FROM tbl_users WHERE user_username = '$user_username'");
$st_1->execute();
if($st_1->rowCount() > 0){$user_exists = '1';}
$st_2 = $handler->prepare("SELECT * FROM tbl_users WHERE user_email = '$user_email'");
$st_2->execute();
if($st_2->rowCount() > 0){$email_exists = '1';}
}
}
Call to function:
$object = new registerClass();
$object->checkUser($user_username, $user_email);
if($user_exists >= '1'){$errors[] = "Username taken";}
if($email_exists >= '1'){$errors[] = "Email taken";}
For some reason the errors never get thrown. I'm not sure what I'm doing wrong here.
The variables you're setting are local to the function, they're not visible in the scope of the caller. Instead, the function should return the variables in an array:
class registerClass{
public function checkUser($user_username, $user_email){
$user_exists = $email_exists = false;
//connect to db via pdo...
$st_1 = $handler->prepare("SELECT * FROM tbl_users WHERE user_username = '$user_username'");
$st_1->execute();
if($st_1->rowCount() > 0){$user_exists = true;}
$st_2 = $handler->prepare("SELECT * FROM tbl_users WHERE user_email = '$user_email'");
$st_2->execute();
if($st_2->rowCount() > 0){$email_exists = true;}
return array($user_exists, $email_exists)
}
}
You can then use it like this:
list($user_exists, $email_exists) = $object->checkUser($user_username, $user_email);
if($user_exists){$errors[] = "Username taken";}
if($email_exists){$errors[] = "Email taken";}
I've also changed the values from strings with 0 and 1 to booleans false/true.
You should use return to return value by function and than in place where you call your function use for example list to get function return values.
Complete code:
<?php
class registerClass
{
public function checkUser($user_username, $user_email)
{
//connect to db via pdo...
$user_exists = 0;
$email_exists = 0;
$st_1 = $handler->prepare(
"SELECT * FROM tbl_users WHERE user_username = '$user_username'"
);
$st_1->execute();
if ($st_1->rowCount() > 0) {
$user_exists = '1';
}
$st_2 = $handler->prepare(
"SELECT * FROM tbl_users WHERE user_email = '$user_email'"
);
$st_2->execute();
if ($st_2->rowCount() > 0) {
$email_exists = '1';
}
return array($user_exists, $email_exists);
}
}
$object = new registerClass();
list($user_exists, $email_exists) = $object->checkUser(
$user_username,
$user_email
);
if ($user_exists >= '1') {
$errors[] = "Username taken";
}
if ($email_exists >= '1') {
$errors[] = "Email taken";
}
However normally you rather don't set value 1 in that case but boolean true so you should rather use this code:
class registerClass
{
public function checkUser($user_username, $user_email)
{
//connect to db via pdo...
$user_exists = false;
$email_exists = false;
$st_1 = $handler->prepare(
"SELECT * FROM tbl_users WHERE user_username = '$user_username'"
);
$st_1->execute();
if ($st_1->rowCount() > 0) {
$user_exists = true;
}
$st_2 = $handler->prepare(
"SELECT * FROM tbl_users WHERE user_email = '$user_email'"
);
$st_2->execute();
if ($st_2->rowCount() > 0) {
$email_exists = true;
}
return array($user_exists, $email_exists);
}
}
$object = new registerClass();
list($user_exists, $email_exists) = $object->checkUser(
$user_username,
$user_email
);
if ($user_exists) {
$errors[] = "Username taken";
}
if ($email_exists) {
$errors[] = "Email taken";
}
When you call a class method like: $object->checkUser($user_username, $user_email); or a function like : checkUser($user_username, $user_email); you must remember that php pass the params by copy, not by reference.
So by default what you pass (for example $user_name), it's not the same $user_name on function/method body. Seee http://php.net/manual/en/functions.arguments.php for more.
You can resolve your problem by using new method declaration this code:
public function checkUser(&$user_username, &$user_email){
//connect to db via pdo...
$st_1 = $handler->prepare("SELECT * FROM tbl_users WHERE user_username = '$user_username'");
$st_1->execute();
if($st_1->rowCount() > 0){$user_exists = '1';}
$st_2 = $handler->prepare("SELECT * FROM tbl_users WHERE user_email = '$user_email'");
$st_2->execute();
if($st_2->rowCount() > 0){$email_exists = '1';}
}
So to have have an argument to a function passed by reference, prepend an ampersand (&):checkUser(&$user_username, &$user_email)
Related
Hi I am trying to create login throttling with object oriented php, I have successfully created it with structured code but I can not get it to work with object oriented so far heres the code:
public function find_failed_login($email = null) {
if(!empty($email)) {
$query = "SELECT * FROM {$this->table} WHERE email = '".$this->db->escape($email)."'";
return $this->db->query($query);
}
}
public function record_failed_login($email) {
$count = 1;
$time = time();
$failed_login = $this->find_failed_login($email);
if(!$failed_login) {
$query = "INSERT INTO {$this->table} (email, count, last_time) VALUES ('".$this->db->escape($email)."', {$count}, {$time})";
return $this->db->query($query);
} else {
$query = "UPDATE {$this->table} SET email = '{$email}', count = count + 1, last_time = {$time}";
return $this->db->query($query);
}
}
public function clear_failed_logins($email = null) {
if(!empty($email)) {
$failed_login = $this->find_failed_login($email);
if(isset($failed_login)) {
$query = "DELETE FROM {$this->table} WHERE email = '".$this->db->escape($email)."'";
return $this->db->query($query);
}
}
}
public function throttle_failed_logins($email = null) {
if(!empty($email)) {
$throttle_at = 3;
$delay_in_minutes = 1;
$delay = 60 * $delay_in_minutes;
$failed_login = $this->find_failed_login($email);
if(isset($failed_login)) {
while($failed = mysqli_fetch_assoc($failed_login)) {
if(isset($failed) && $failed['count'] >= $throttle_at) {
$remaining_delay = ($failed['last_time'] + $delay) - time();
$remaining_delay_in_minutes = ceil($remaining_delay / 60);
return $remaining_delay_in_minutes;
} else {
return 0;
}
}
}
}
}
and in the login page I am calling it like this:
$objLogin = new Login();
if($objForm->isPost('login_email')) {
$throttle_delay = $objLogin->throttle_failed_logins($objForm->getPost('login_email'));
if($throttle_delay > 0) {
$objValid->add2Errors('failed_logins');
}
when I try this I get no error or anything for that matter, its like it is dead code, would appreciate some professional help :)
Below is the function I am using. It is strange because when I test the name "admin" it returns an associative array with all the correct columns and values, however every other name tests returns 0 as far as I can tell, meaning nothing is found from the query (I am entering the names perfectly as they are in the database).
I have a feeling this could be some sort of security feature of pdo or something but I don't understand why it is acting up this way.
I am using mysql.
Does anyone know the problem and how to resolve it? Thank you!
function getUserDetailsByName($name, $fields = "*")
{
$db = connect_db();
$query = "SELECT $fields FROM UserDetails WHERE userName=:username";
$result = $db->prepare($query);
$result->bindParam(":username", $name);
if (!($result->execute())) {
sendMessage (1,1,'Query failed',$query);
$db = null;
return;
}
if (!($result->fetch(PDO::FETCH_NUM) > 0)) {
$db = null;
return 0;
}else{
$result = $result->fetch();
$db = null;
return $result;
}
}
EDIT: Someone asked to post how I call the function.
$user = getUserDetailsByName($_POST['value']);
if($user == 0)
{
print "user = 0";
}
print_r($user);
function getUserDetailsByName($name, $fields = "*"){
$db = connect_db();
$query = "SELECT {$fields} FROM UserDetails WHERE userName = :username LIMIT 1;";
if(!$result = $db->prepare($query)){
return null;
}
$result->bindParam(":username", $name);
if(!$result->execute()) {
sendMessage (1,1,'Query failed',$query);
return null;
}
if(!$user = $result->fetch(PDO::FETCH_NUM)) {
return false;
}
return $user;
}
Why 2 fetches? Checkout and compare this to your code.
Use like this:
if($user = getUserDetailsByName($_POST['value'])){
// we have a user!
}else{
// we don't have a user!
}
hello i have problems while using crypt function. i would like to check passwords from a database and an entered one.
the problem i have is that when i will enter a password it even will redirect even in case when it is a totally different password? this is strange to me.
so i use this function:
function salt_crypt($login_password, $rounds = 7) {
$salt = "";
$salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9)); for($i=0; $i < 22; $i++) {
$salt .= $salt_chars[array_rand($salt_chars)];
}
return crypt($login_password, sprintf('$2a$%02d$', $rounds) . $salt);
i will get the stored password from a function that returns an array:
function ab($a){
global $db;
$query = $db->query("SELECT col_a, col_b FROM table WHERE Field= '$a' ");
$check = $query->fetch_assoc();
return ($check);
}
and this will be used in this function:
function login($a, $login_password){
$user_data = user_data($a);
global $db;
$uname = sanitize($uname);
$crypted_password = salt_crypt($login_password);
if(crypt($user_data['col_b'], $crypted_password) == $crypted_password) {
$query = $db->query("SELECT col_a FROM table WHERE Field_a= '$a' AND Field_b = '$crypted_password' ");
$check = $query->num_rows;
return ($check == 1) ? true : false;
}
}
this function wil be called and in case of the returning result header with:
$login = login($a, $login_password);
if ($login === false){
$errors[] = "text";
} else {
header('Location: page.php');
}
Not all code paths return a value -> your function will return true, even if the if statement is false. Try it with something like this:
function login($a, $login_password){
//All your stuff
if(crypt($user_data['col_b'], $crypted_password) == $crypted_password) {
//Your stuff
}
return false
}
I'm trying to build a REST api(using Restler) which takes in username and password for login and generates a session key. Once sessionkey is generated, user will be able to pass this session key to access other classes in the api. Is it possible to get the name of the class that invokes __isAuthenticated function?
My Auth Class:
<?php
class Auth implements iAuthenticate
{
public static $sessionKey;
public static $currentUser;
public $tempsesskey;
function __isAuthenticated ()
{
if (isset($_GET['useremail']) && isset($_GET['userpass'])) {
$user = $_GET['useremail'];
$pass = $_GET['userpass'];
$user = mysql_real_escape_string($user);
$pass = mysql_real_escape_string($pass);
mysql_query(
"UPDATE `userdetail` SET lastlogin=NOW()
WHERE useremail='$user' AND userpass=md5('$pass')");
if (mysql_affected_rows() > 0) {
$result = mysql_query(
"SELECT sessionkey from usersession where TIMESTAMPDIFF(MINUTE,lastactivity,now()) < 20 and useremail='$user'");
while ($row = mysql_fetch_assoc($result)) {
$tempsesskey = $row['sessionkey'];
}
if (strlen($tempsesskey) > 0) {
mysql_query(
"UPDATE usersession set lastactivity=now() where sessionkey='$tempsesskey'");
} else {
$tempsesskey = generateKey(52);
mysql_query(
"UPDATE `usersession` set sessionkey='$tempsesskey',keyvalid='Y' where useremail='$user'");
}
self::$currentUser = $user;
self::$sessionKey = $tempsesskey;
return TRUE;
}
} else
if (isset($_GET['sessionkey'])) {
$sesskey = $_GET['sessionkey'];
$sesskey = mysql_real_escape_string($sesskey);
$result = mysql_query(
"SELECT sessionkey from usersession where sessionkey='$sesskey' and TIMESTAMPDIFF(MINUTE,lastactivity,now()) < 20");
if (mysql_affected_rows() > 0) {
while ($row = mysql_fetch_assoc($result)) {
$tempsesskey = $row['sessionkey'];
self::$sessionKey = $tempsesskey;
}
return TRUE;
}
}
}
}
There is a simple way of setting the property on the Authentication class by adding custom php doc comment /annotation which is explained in Authentication with ACL. You can use the same technique for your purpose as well
This is the login function written using MySQL way
However, the problem exists when it convert into PDO way
MYSQL:
<?
function confirmUser($username, $password){
global $conn;
if(!get_magic_quotes_gpc()) {
$username = addslashes($username);
}
/* Verify that user is in database */
$q = "select UserID,UserPW from user where UserID = '$username'";
$result = mysql_query($q,$conn);
if(!$result || (mysql_numrows($result) < 1)){
return 1; //Indicates username failure
}
/* Retrieve password from result, strip slashes */
$dbarray = mysql_fetch_array($result);
$dbarray['UserPW'] = stripslashes($dbarray['UserPW']);
$password = stripslashes($password);
/* Validate that password is correct */
if($password == $dbarray['UserPW']){
return 0; //Success! Username and password confirmed
}
else{
return 2; //Indicates password failure
}
}
PDO:
<?
function confirmUser($username, $password){
global $conn;
include("connection/conn.php");
$sql = '
SELECT COALESCE(id,0) is_row
FROM user
WHERE UserID = ?
LIMIT 1
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('09185346d'));
$row = $stmt->fetch();
if ($row[0] > 0) {
$sql = '
SELECT COALESCE(id,1) is_row
FROM user
WHERE UserPW = ?
LIMIT 1
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('asdasdsa'));
$row = $stmt->fetch();
if ($row[0] > 0)
return 2;
else
return 0;
}
elseif ($row[0] = 0)
{return 1;}
}
What is the problem ?? And is it necessary to include bind parameter in PDO??? THANKS
Aside from your use of global and your include inside the function (you should investigate an alternative way of structuring your function not to do this), I would change the code as follows:
$sql =
'SELECT id
FROM user
WHERE UserID = ?
AND UserPW = ?
LIMIT 1';
$stmt = $conn->prepare($sql);
$stmt->execute(array(
'09185346d',
'asdasdsa'
));
if ($stmt->rowCount() == 1) {
return 0;
}
else {
return 1;
}
Combing the queries to give a general Authentication error, instead of allowing people to trial valid usernames, and then valid passwords, and then using PDOStatements rowCount method do see if your row was returned.
To answer your second part, it is not necessary to specifically use bindParam to prevent SQL injection.
Here's a quick example of the difference between bindParam and bindValue
$param = 1;
$sql = 'SELECT id FROM myTable WHERE myValue = :param';
$stmt = $conn->prepare($sql);
Using bindParam
$stmt->bindParam(':param', $param);
$param = 2;
$stmt->execute();
SELECT id FROM myTable WHERE myValue = '2'
Using bindValue
$stmt->bindValue(':param', $param);
$param = 2;
$stmt->execute();
SELECT id FROM myTable WHERE myValue = '1'