Mostly a security question
Currently I am using session variables to determine who is viewing the website and then matching the users session name vs the profile name being viewed. If these match then the profile will be editable (since it is their profile).
I am using:
$pid = $_GET['pid']; // Profile being viewed
$edit = $_GET['edit']; // true/false for editing
$username = $_SESSION['username'];
$pclass = new user_profile($db, $pid, $username);
$pclass just takes my database connection, profile that is being viewed and the user viewering.
class user_profile {
private $db;
private $viewer;
public function __construct(\database $db, $pid, $viewer) {
$this->db = $db;
$this->username = $pid;
$this->viewer = $viewer;
}
}
for displaying the edit button and then allowing the user to view the edit page I use a method myProfile() which is simply:
public function myProfile() {
if($this->username === $this->viewer) {
return true;
}
else {
return false;
}
}
Is this a secure enough way to stop users editing other peoples profiles or is there another way around it how this should be done?
Given the information that you supplied, this is a secure way of doing this.
$_SESSION is something you control on the server, and can't be modified by the user.
Related
What I am trying to do is to display to an guest/visitor to a Joomla site that a certain member is currently logged in or not. What I have so far is this:
//First assigned user object to $user variable
$user = & JFactory::getUser();
if($user->guest){
//Check user id is zero, if it is zero means user not logged in Joomla
if ($user->id == 638) {
echo "online.";
} else {
echo "offline.";
}
}
However this does not work. I have this method which works only for the person that matches the user id:
//First assigned user object to $user variable
$user = & JFactory::getUser();
//Check user id is zero, if it is zero means user not logged in Joomla
if ($user->id == 638) {
echo "online.";
} else {
echo "offline.";
}
}
But I can't make the work for the guest user. Any help is greatly appreciated.
Joomla user object return current user's(who is browsing) data. You need to check session table's data. This table store session info.
$db =& JFactory::getDBO();
$db->getQuery(true);
$query = 'SELECT COUNT(userid) FROM #__session WHERE userid = 638';
$db->setQuery($query);
$loggedin = $db->loadResult();
if($loggedin){
echo "online.";
} else {
echo "offline";
}
Hey guys I have a question and I still consider myself pretty new at coding, so forgive me if I come off foolish.
I am studying in school as of now and we have a project to build a full stack recreation of craigslist. Any who the problem I am having deals with PHP. I have created an account page with text areas. I would like to echo out the user's information on their so the user can see what he put on and update as he likes. Since my navbar is included on every page, I added the code:
if(isset($_SESSION['logged_in_user'])){
var_dump($_SESSION['logged_in_user']);
$user = $_SESSION['logged_in_user'];
var_dump($user);
}
on my account page I figured I can echo it out as
<?= $attributes['first_name']?> within the placeholders. But I keep getting:
Undefined index: first_name
Also when I var_dump($user) I get an protected $attributes array.
In My Auth class is where I first defined $user as such:
public static function attempt($attemptedUsername, $attemptedPassword) {
$user = User::findByUserName($attemptedUsername);
if ($user == null) {
return false;
}
$validPassword = password_verify($attemptedPassword,$user->password);
if ($validPassword == true) {
$_SESSION['logged_in_user'] = $user;
}
return false;
}
and my findByUserName function is in the user class. the code is:
public static function findByUserName($user_name){
// Get connection to the database
self::dbConnect();
$stmt = self::$dbc->prepare('SELECT * FROM users WHERE user_name = :user_name');
$stmt->bindValue(':user_name', $user_name , PDO::PARAM_STR);
//execute gets its own line, t or false
$stmt->execute();
$result=$stmt->fetch(PDO::FETCH_ASSOC);
// #TODO: Create select statement using prepared statements
// #TODO: Store the result in a variable named $result
// The following code will set the attributes on the calling object based on the result variable's contents
$instance = null;
if ($result) {
$instance = new static($result);
}
return $instance;
}
Your problem seems to be with not being able to access the variable $user outside of the static method attempt() this can be fixed by declaring the variable globally at the beginning of the method attempt() like this:
public static function attempt($attemptedUsername, $attemptedPassword) {
global $user;
$user = User::findByUserName($attemptedUsername);
if ($user == null) {
return false;
}
$validPassword = password_verify($attemptedPassword,$user->password);
if ($validPassword == true) {
$_SESSION['logged_in_user'] = $user;
}
return false;
}
More information can be found on this in the PHP documentation here.
I am developing an e-commerce website on which i need to store sessions inside database.I did that by implementing SessionHandlerInterface Class that is provided by the php itself.However it works totally fine and did store sessions inside the database , as well as read them properly.
However I am facing problem when I am using unset to unset a session variable.Sometimes it does work.Sometimes it doesn't.
For example:If i have a session variable by the name ABC unset might delete it from the database or it doesn't deletes the variable.
<?php
//inc.session.php
require_once 'RemoteAddress.php';
class SysSession implements SessionHandlerInterface
{
private $remote_write;
private $remote_read;
private $link;
private $ip_address_write;
private $ip_address_read;
public function open($savePath, $sessionName)
{
$link = new mysqli("localhost","root","","cakenbake");
if($link){
$this->link = $link;
return true;
}else{
return false;
}
}
public function close()
{
mysqli_close($this->link);
return true;
}
public function read($id)
{
$this->remote_read=new RemoteAddress();
$this->ip_address_read=$this->remote_read->getIpAddress();
$stmt=$this->link->prepare("SELECT `Session_Data`,`ip_address` FROM Session WHERE `Session_Id` = ? AND `Session_Expires` > '".date('Y-m-d H:i:s')."'");
$stmt->bind_param("s",$id);
$stmt->execute();
//$result = mysqli_query($this->link,"SELECT Session_Data FROM Session WHERE Session_Id = '".$id."' AND Session_Expires > '".date('Y-m-d H:i:s')."'");
/*$result=$this->link->prepare("Some query inside")
* This shows up an error stating prepare method not found
*
*/
$res=$stmt->get_result();
if($row=$res->fetch_assoc()){
if($this->ip_address_read==$row['ip_address'])
return $row['Session_Data'];
else return "";
}else{
return "";
}
}
public function write($id, $data)
{
$this->remote_write=new RemoteAddress();
$this->ip_address_write=$this->remote_write->getIpAddress();
if(!empty($data))
{
$DateTime = date('Y-m-d H:i:s');
$NewDateTime = date('Y-m-d H:i:s',strtotime($DateTime.' + 1 hour'));
$stmt=$this->link->prepare("REPLACE INTO Session SET Session_Id = ?, Session_Expires = '".$NewDateTime."', Session_Data = '".$data."', ip_address = '".$this->ip_address_write."'");
$stmt->bind_param("s",$id);
// $result = mysqli_query($this->link,"REPLACE INTO Session SET Session_Id = '".$id."', Session_Expires = '".$NewDateTime."', Session_Data = '".$data."'");
if($stmt->execute()){
return true;
}else{
return false;
}
}
}
public function destroy($id)
{
$stmt = $this->link->prepare("DELETE FROM Session WHERE Session_Id =?");
$stmt->bind_param("s",$id);
if($stmt->execute()){
return true;
}else{
return false;
}
}
public function gc($maxlifetime)
{
$result = $this->link->query("DELETE FROM Session WHERE ((UNIX_TIMESTAMP(Session_Expires) + ".$maxlifetime.") < UNIX_TIMESTAMP(NOW()))");
if($result){
return true;
}else{
return false;
}
}
}
$handler = new SysSession();
session_set_save_handler($handler, true);
?>
The above code stores and read sessions from the database.
Structure of the session table.
What could be the possible reason for this weird behaviour. Do i have to implement unset function as well?.
How should i resolve this problem?
If you could suggest me someother already written code for storing in database.That would work as well but i dont need any frameworks such as codeigniter and Yii2.
If you need more information regarding this problem.I will update my question.
Thanks in advance!
The problem is not with the unset function but with your write function.The write function is responsible for any updates that are made to the specific session id.
The wierd behiviour is not with the unset but it is with the write funciton you have implemented.
See ,the !empty constraint checks if your data is empty or not.What i can guess is that your database for that specific id must be empty after the removal of the specific variable .So the write tries to update your row with an empty value but with that constraint it isn't able to do so.
Just remove the !empty tag and it will work like a charm.
i am trying to get my head around sessions and how to use them to show user data and grant access to areas of the site etc...
i have session_start(); at the beginning of my config file, then proceed to do the connection to database etc...
i then have a User.php class which is as follows:
<?php
include('Password.php');
class User extends Password{
private $db;
function __construct($db){
parent::__construct();
$this->_db = $db;
}
public function is_logged_in(){
if(isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true){
return true;
}
}
private function get_user_hash($username){
try {
$stmt = $this->_db->prepare('SELECT password FROM members WHERE username = :username');
$stmt->execute(array('username' => $username));
$row = $stmt->fetch();
return $row['password'];
} catch(PDOException $e) {
echo '<p class="error">'.$e->getMessage().'</p>';
}
}
public function login($username,$password){
$hashed = $this->get_user_hash($username);
if($this->password_verify($password,$hashed) == 1){
$_SESSION['loggedin'] = true;
return true;
}
}
public function logout(){
session_destroy();
}
}
?>
which when i use var_dump($_SESSION); returns:
array(1) { ["loggedin"]=> bool(true) }
what i am wanting to do is have things like "Hello, '(persons username)' welcome to the '(basic,premium,admin etc...)' area of the site".
so i think i want to be doing things like $_SESSION['memberID'], $_SESSION['username'], $_SESSION['level']
so... first of all am i looking at the right area to do this kind of thing (User.php) and would modifying anything i already have allow me to do this, or do i need to create another function(s) and query the database etc... if i do things like $_SESSION['username'] = 'mee'; then it will display 'mee', but what i am wanting to do is get the username for whichever user is logged in.
*apologies in advance if this makes little sense or is confusing, iv been trying to figure this out for some time now and literally nothing im doing makes sense - brain overload :/
For security purposes it is prudent to query the database for every subsequent request to restricted areas in your application. This can be achieved by simply storing the user id in the session variable and pulling the user data with every request by the stored user id. This way if access is revoked while the user is still logged in the system will respond correctly
This functionality could be achieved like so:
// after successfully getting user by the provided username/password
$_SESSION['logged_in_user_id'] = $user['id']
Now, on every request you simply check:
if (isset($_SESSION['logged_in_user_id'])) {
$currentUser = (new User())->find($_SESSION['logged_in_user_id']);
}
In your user model you could do something like this:
public function find($id) {
try {
$stmt = $this->_db->prepare('SELECT name, address, user_level, email FROM members WHERE id = :id');
$stmt->execute(array('id' => $id));
$row = $stmt->fetchAll();
$user = new self();
$user->fill($row[0]);
return $user;
} catch(PDOException $e) {
echo '<p class="error">'.$e->getMessage().'</p>';
} catch (Exception $e) {}
return null;
}
public function fill(array $data) {
foreach ($data as $key => $value) {
$this->$key = $value;
}
return $this;
}
To log the user out:
unset($_SESSION['logged_in_user_id']);
This method has the added benefit of keeping sensitive user data out of the plain text session files on your server which could be read by anyone with access to the box.
Now, with sessions you do need to keep in mind the potential for session hijacking but that is another discussion and there are tons of PHP packages out there to help protected against this vulnerability.
If you are not concerned with security and just want to get it working with as little effort as possible (not recommended) you can simply store the user data array in the session and use whatever you need from it:
Log in code:
public function login($username,$password){
if ($user = $this->getWithCredentials($username, $password) {
$_SESSION['logged_in_user'] = json_encode($user);
return true;
}
return false;
}
public function getWithCredentials($username, $password) {
try {
$hashedPassword = $this->myPasswordHashAlgorithm($password);
$stmt = $this->_db->prepare('SELECT id, name, address, email FROM members WHERE username = :username AND password = :password');
$stmt->execute(array('username' => $username, 'password' => $hashedPassword));
$row = $stmt->fetch();
return $row;
} catch(PDOException $e) {
echo '<p class="error">'.$e->getMessage().'</p>';
} catch (Exception $e) {}
return null;
}
Then, to get user data on subsequent requests:
$user = isset($_SESSION['logged_in_user']) ? json_decode($_SESSION['logged_in_user'] : null;
i found a user login script online which i later foundd out had been written in PHP4, and i am in the process of updating it to PHP5 and learning OOP at the same time :)
a snippet of my user class is
<?php
session_start(); //Tell PHP to start the session
include("include/database.php");
include("include/mailer.php");
include("include/form.php");
include("constants.php");
class user
{
var $username; //Username given on sign-up
var $firstname;
var $lastname;
var $userid; //Random value generated on current login
var $userlevel; //The level to which the user pertains
var $time; //Time user was last active (page loaded)
var $logged_in; //True if user is logged in, false otherwise
var $userinfo = array(); //The array holding all user info
var $url; //The page url current being viewed
var $referrer; //Last recorded site page viewed
var $num_active_users; //Number of active users viewing site
var $num_active_guests; //Number of active guests viewing site
var $num_members; //Number of signed-up users
/**
* Note: referrer should really only be considered the actual
* page referrer in process.php, any other time it may be
* inaccurate.
*/
public function __construct(db $db, Form $form)
{
$this->database = $db;
$this->form = $form;
$this->time = time();
$this->startSession();
$this->num_members = -1;
if(TRACK_VISITORS)
{
/* Calculate number of users at site */
$this->calcNumActiveUsers();
/* Calculate number of guests at site */
$this->calcNumActiveGuests();
}
}
/**
* startSession - Performs all the actions necessary to
* initialize this session object. Tries to determine if the
* the user has logged in already, and sets the variables
* accordingly. Also takes advantage of this page load to
* update the active visitors tables.
*/
function startSession()
{
/* Determine if user is logged in */
$this->logged_in = $this->checkLogin();
/**
* Set guest value to users not logged in, and update
* active guests table accordingly.
*/
if(!$this->logged_in)
{
$this->username = $_SESSION['username'] = GUEST_NAME;
$this->userlevel = GUEST_LEVEL;
$this->addActiveGuest($_SERVER['REMOTE_ADDR'], $this->time);
}
/* Update users last active timestamp */
else
{
$this->addActiveUser($this->username, $this->time);
}
/* Remove inactive visitors from database */
$this->removeInactiveUsers();
$this->removeInactiveGuests();
/* Set referrer page */
if(isset($_SESSION['url']))
{
$this->referrer = $_SESSION['url'];
}
else
{
$this->referrer = "/";
}
/* Set current url */
$this->url = $_SESSION['url'] = $_SERVER['PHP_SELF'];
}
/**
* checkLogin - Checks if the user has already previously
* logged in, and a session with the user has already been
* established. Also checks to see if user has been remembered.
* If so, the database is queried to make sure of the user's
* authenticity. Returns true if the user has logged in.
*/
function checkLogin()
{
/* Check if user has been remembered */
if(isset($_COOKIE['cookname']) && isset($_COOKIE['cookid']))
{
$this->username = $_SESSION['username'] = $_COOKIE['cookname'];
$this->userid = $_SESSION['userid'] = $_COOKIE['cookid'];
}
/* Username and userid have been set and not guest */
if(isset($_SESSION['username']) && isset($_SESSION['userid']) && $_SESSION['username'] != GUEST_NAME)
{
/* Confirm that username and userid are valid */
if($this->confirmUserID($_SESSION['username'], $_SESSION['userid']) != 0)
{
/* Variables are incorrect, user not logged in */
unset($_SESSION['username']);
unset($_SESSION['userid']);
return false;
}
/* User is logged in, set class variables */
$this->userinfo = $this->getUserInfo($_SESSION['username']);
$this->username = $this->userinfo['username'];
$this->userid = $this->userinfo['userid'];
$this->userlevel = $this->userinfo['userlevel'];
$this->lastlogin = $this->userinfo['lastlogin'];
$this->townid = $this->userinfo['placeID'];
return true;
}
/* User not logged in */
else
{
return false;
}
}
}
$db = new db($config);
$form = new Form;
$user = new User($db, $form);
but i've been told the var $username; etc are not very secure and should not be used, so im here to ask what should i use instead?
do i do something like this for each var?
private $username;
/**
* #return the $username
*/
public function getUsername() {
return $this->username;
}
/**
* #param $newUsername
* the username to set
*/
public function setUsername($newUsername) {
$this->username = $newUsername;
}
thanks
var is equivalent to public. By making all the member variables private and adding getters (but not setters) to each of them, you're effectively making it so that other developers who use your API cannot [accidentally] update the values. That's what's meant by "secure" -- it's not as though someone will be able to hack into your server or access data if you don't declare them with the right privacy level*.
If you're going to add a setter as well, I'd say you're wasting your time (although others will disagree with me). You've giving them full reign over the variable anyway. The only advantage is that you can squeeze some other computations in your getter/setter down the road if you decide you want to store the value differently.
* Although another developer might accidentally expose information he shouldn't, such as a password.