The below code may / may not have many hidden errors.
What I want:- I have session which results as if a user is at index.php and is logged, it will redirect to its account folder.
What I got:- In index.php I got see image.
How account folder is prescribed:-
Suppose there are two users, having uname as trial & demo
So the account folder for trial will be http://localhost/Ebooks/new/trial & for demo it will be http://localhost/Ebooks/new/demo
Means account folders are based on their uname
uname is nothing but username
For getting the result I tried:-
index.php
<?php
session_start();
require_once 'class.user.php';
$user_login = new USER();
if($user_login->is_logged_in()!="")
{
$user_login->redirect($uname);
}
if(isset($_POST['btn-login']))
{
$uname = trim($_POST['txtuname']);
$upass = trim($_POST['txtupass']);
if($user_login->login($uname,$upass))
{
$user_login->redirect($uname);
}
}
?>
class.user.php
public function is_logged_in()
{
if(isset($_SESSION['userSession']))
{
return true;
}
}
public function redirect($uname)
{
try{
$stmt = $this->conn->prepare("SELECT * FROM tbl_users WHERE userName=:username");
$stmt->execute(array(":username"=>$uname));
header("Location: $uname");
} catch (Exception $e) {
die('Error! '.$e->getMessage());
}
}
public function logout()
{
session_destroy();
$_SESSION['userSession'] = false;
}
But I get the result as see image.
I request to sort out my problem!
If my error is solved please do not consider the problem is solved. I want basically How to go to account folder using session in PHP, but this may have many hidden problems.
You need a catch if you are goiung to try something:
public function redirect($uname)
{
try{
$stmt = $this->conn->prepare("SELECT * FROM tbl_users WHERE userName=:username");
$stmt->execute(array(":username"=>$uname));
header("Location: $uname");
} catch (Exception $e) {
die('Error! '.$e->getMessage());
}
}
Handle any errors however you will in the catch area.
You need catch block as well with try. I assume you use PDO, so working solution would be following.
public function redirect($uname) {
try{
$stmt = $this->conn->prepare("SELECT * FROM tbl_users WHERE userName=:username");
$stmt->execute(array(":username"=>$uname));
}
catch(PDOException $error) {
return $error->getMessage();
}
header("Location: $uname");
}
Related
guys if i change my hosting i get a error in my local ampps host i not have not one problem now i see this error everithing is same php version is 7.1 and in local is 7.1 but why i get this error?
This is error code :
Fatal error: Uncaught Error: Call to a member function userDetails() on null in /home/root/requests/index.php:14 Stack trace: #0 {main} thrown in /home/root/requests/index.php on line 14
this is my function in top of index.php
<?php
include('config.php');
include('session.php');
$userDetails=$userClass->userDetails($session_uid);
this is my session.php code
<?php
if(!empty($_SESSION['uid']))
{
$session_uid=$_SESSION['uid'];
include('userClass.php');
$userClass = new userClass();
}
if(empty($session_uid))
{
$url=BASE_URL.'/login.php';
header("Location: $url");
}
?>
this is my userClass.php code :
<?php
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password");
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
return true;
}
else
{
return false;
}
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>
Did you defined $userClass, if not then you should make an object the userClass that you are using here then call the method inside that class and it will work.
if(isset($_POST["submit"]))
{
$email = trim($_POST['email']);
$upass = trim($_POST['password']);
if($user_login->login($email,$upass))
{
$user_login->redirect("index.php");
}
}
public function login($email,$upass)
{
try
{
$stmt = $this->conn->prepare("SELECT * FROM table WHERE userEmail=:email_id");
$stmt->execute(array(":email_id"=>$email));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() == 1)
{
if($userRow['userStatus']=="Y")
{
if($userRow['userPass']==md5($upass))
{
$_SESSION['userSession'] = $userRow['userID'];
return true;
}
else
{
header("Location: login.php?error");
exit;
}
}
else
{
header("Location: login.php?inactive");
exit;
}
}
else
{
header("Location: login.php?error");
exit;
}
}
catch(PDOException $ex)
{
echo $ex->getMessage();
}
I've granted all the privileges to the database.
The user is able to signup but when loggedin it doesn't log in but also doesn't show any error and directs the user to index.php without creating session.
If you haven't already, I would recommend adding the following line of code to the top of all relevant pages which require Session based integration. Following this, you'll be able to set the session variables.
session_start();
With regards to the previous comment regarding the password Hashing methods, MD5 is considered very insecure compared to other methods of password hashing, including PHP's password_hash() and password_verify() functions.
<?php
$hashed_pass = password_hash($password, PASSWORD_BCRYPT);
if(password_verify($input_pass,$hashed_pass)) {
//Password Matches DB
}
else {
//Pass Doesn't Match DB
}
?>
I also see you use a lot of GET variables for the error messages, such as error and inactive. I would personally reccomend using the POST method on the Login form itself, and return back to itself, and handle the error messages that way, with the backend processes such as logging in etc being handled from the backend class.
I am getting a 404 response when I use $http.get to fetch the list of users from my backend API, which is built using Slim.
This is my AngularJS method to call
function ListCtrl($scope, $http) {
$http.get('api/getuser.php/getUser').success(function(data) {
$scope.users = data;
});
}
This is my Slim route, located in getuser.php:
$app = new Slim();
$app->get('/getUser', 'getUser');
$app->run();
function getUser() {
$sql = "select * FROM employees ORDER BY id";
try {
$db = getConnection();
$stmt = $db->query($sql);
$wines = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo json_encode($wines);
} catch(PDOException $e) {
echo '{"error":{"text":"'. $e->getMessage() .'"}}';
}
}
Thanks for replies in advance:)
Don't you need to register a function instead of a string?
Try:
$app->get('/getUser', getUser);
http://docs.slimframework.com/routing/get/
I was wondering if the following program flow will prevent the finally from being run in this try-catch-finally block due to a return in the try.
Please excuse poor error checking and sanitisation, this is just a mock:
function doLogin() {
$dbh = new PDO('mysql:host=localhost;dbname=test', "root", "");
$errors = array();
$loginSuccess = false;
try {
$query = $dbh->prepare('SELECT *
FROM users
WHERE username = :username');
$query->bindParam(':username', $_POST['username'], PDO::PARAM_STR);
$result = $query->fetch(PDO::FETCH_ASSOC);
if (!password_verify($_POST['password'], $result['password'])) {
array_push($errors, 'Invalid password.');
return; // will this return prevent the finally from being run?
}
else {
$loginSuccess = true;
}
}
catch (PDOException $pdoEx) {
echo 'Error occurred ' . $pdoEx->getMessage();
}
finally {
$dbh = null;
}
}
Code is pretty poorly written, but hopefully you understand my point.
The answer is yes, the code in finally will be run.
For example:
function example() {
try {
return true;
}
catch(Exception $e){
echo "error";
}
finally{
return false;
}
}
var_dump( example() );
Outputs:
bool(false)
It's also (hiddenly) stated in the docs:
In PHP 5.5 and later, a finally block may also be specified after the
catch blocks. Code within the finally block will always be executed
after the try and catch blocks, regardless of whether an exception has
been thrown, and before normal execution resumes.
To my understanding the try block finishes with the return statement. The normal execution is "paused" and the finally executed.
So the problem is, when /MVCTest/manage/dashboard is called, the authenticator is failing because authenticate (a method in the authenticator class) is not finding $_SESSION['user_id'], so it kicks the user back to the login page.
However, if I change the action below to:
action="/MVCTest/manage/login?target=MVCTest/manage/dashboard"
and add the same login function form the index controller to the manageController, everything works fine, but this means I would have to have a login function in every controller that has a page I want to login from (which is every page since I want a user dashboard).
So how do I get the $_SESSION to presist between controllers so I can have a single controller responsible for logging a user in/out?
First, some code...
action="/MVCTest/index/login?target=MVCTest/manage/dashboard" calls the login action of the indexController.
<?php
Class indexController Extends Core_Controller {
public function login(){
$this->registry->authenticator->login($_POST);
}
}
?>
The authenticator object was created in the bootstrap and assigned to the registry. Now for the authenticator object.
<?php
Class Authenticator Extends Base_Model {
public function login($credentials){
//Select user from the database based on email/username
try{
$STH = $this->db->prepare("SELECT * FROM user_account WHERE email = ? OR username = ?");
$STH->bindParam(1, $credentials['login']);
$STH->bindParam(2, $credentials['login']);
$STH->execute();
while($user = $STH->fetch(PDO::FETCH_OBJ)){
$password = $user->user_salt.$credentials['password'];
$password = $this->hashData($password);
try{
if($password === $user->password){
//Active and Verified user exists, set sessions
$random = $this->generateRandomString();
//Build the token
$token = $_SERVER["HTTP_USER_AGENT"] . $random;
$token = $this->hashData($token);
//Setup session variables
session_start();
$_SESSION["token"] = $token;
$_SESSION["user_id"] = $user->id;
//Delete old session records for the user
$STH = $this->db->prepare("DELETE FROM user_session WHERE user_account_id = ?");
$STH->bindParam(1, $user->id);
$STH->execute();
//Insert new session records for the user
try{
$STH = $this->db->prepare("INSERT INTO user_session (user_account_id, session_id, token)
VALUES (?,'".session_id()."', ?);");
$STH->bindParam(1, $user->id);
$STH->bindParam(2, $token);
$STH->execute();
header("Location: /{$_GET['target']}");
exit;
} catch (PDOException $e){
file_put_contents(__SITE_PATH."/logs/errors/MySQLErrors", $e->getMessage()."\n", FILE_APPEND);
die($e->getMessage());
}
} else {
throw new Exception("Password is incorrect!");
}
} catch (Exception $e){
file_put_contents(__SITE_PATH."/logs/errors/LoginErrors", $e->getMessage()."\n", FILE_APPEND);
die($e->getMessage());
}
}
//Email/Username not found
throw new Exception("Email/Username not found!");
} catch (Exception $e) {
file_put_contents(__SITE_PATH."/logs/errors/LoginErrors", $e->getMessage()."\n", FILE_APPEND);
die($e->getMessage());
} catch (PDOException $e){
file_put_contents(__SITE_PATH."/logs/errors/MySQLErrors", $e->getMessage()."\n", FILE_APPEND);
die($e->getMessage());
}
}
}
?>
And finally, my manageController
<?php
session_name();
session_set_cookie_params(3600, "/MVCTest/manage/");
session_start();
Class manageController Extends Core_Controller {
public function index() {
if(isset($_SESSION['user_id'])){
header("Location: /MVCTest/manage/dashboard");
exit;
}
$this->registry->template->show('manage/index');
}
public function dashboard(){
$this->registry->authenticator->authenticate("/MVCTest/manage/");
$this->registry->template->show('manage/dashboard');
}
}
?>
I found the answer. Leave session_name();
session_set_cookie_params(3600, __SITE_PATH.'/MVCTest/manage/'); in the manageController while moving session_start(); to the beginning of the extended Core_Controller while adding a public login function.
The result is that every page can log somebody in; however, I feel like this is bad practice. The problem I see is that every single page call will start a session regardless of if the user is logged in or not. I get the feeling that this is bad, any suggestions?
Look at this code:
//Setup session variables
session_start();
$_SESSION["token"] = $token;
$_SESSION["user_id"] = $user->id;
You must use
session_start();
At the beginning of the file.
Read more about session_start