Welcome Guest, Not a member yet? Register   Sign In
Sessions
#1

[eluser]richzilla[/eluser]
Hi all, ive run into a bit of mental block with code igniter sessions, ive never authenticated users on sessions saved in a database etc. are there any good tutorials out there that would give you a quick run down on CI sessions, (the user guide skims over it a bit) or could anybody explain it to me in brief?

thanks
#2

[eluser]jrtashjian[/eluser]
I wrote an article on my blog running through how to do this with hard-coded users. But, it can EASILY be modified to use a database. Here is the article: http://jrtashjian.com/2009/02/10/simple-...deigniter/

I actually just started a series where I will walk through how to create a user management system with MySQL. The first part is here: next part will come next week...http://jrtashjian.com/2009/08/31/user-ma...em-part-1/
#3

[eluser]BrianDHall[/eluser]
The thing I learned when coding authorization the first time in CI is it isn't nearly as complicated or as hard as it seems like it might be. It's really very simple, so don't fret.

The easiest way I found is first you make your model to control your users. If you use ORM like DataMapper (or any other) it simplifies some things, but for instance you might have:

Users Model:
createuser($username, $password)
login($username, $password)
loaduserdata($userid)

So then you can call createuser('testaccount', 'testpass') and tada, new user added.

Then you make a form to take username and password, and you run login($this->input->post('username'), $this->input->post('password')).

In login() you check to see if username and password matches an existing user, and if not you return false - so in your script you check if the function returned false, meaning failed login, or true, meaning success. If the user does exist you call loaduserdata($userid) from your login() function.

In loaduserdata() you actually load your session data, such as:

Code:
$this->session->set_userdata('userid', $userid);
$this->session->set_userdata('username', $username);
$this->session->set_userdata('password', $password);

Since you use autoload in CI on Session (and you will want to do that) much else is magic.

For unbuggyness you will want a logout() function that calls unset_userdata() on at least your userid, username, and password. Saves many headaches that leave you wondering, 'why the hell am I still logged in, I pressed logout?!?'.

So, now with that done if you want to make sure someone is logged in you just run:

Code:
if ($this->session->userdata('userid'))

And if true the user is logged in, and if not they are logged out.

Now, one piece I found very useful and important:

In the controller's constructor I put in code to validate the session, so if there userid is set in the session data I call login() with the username and password, just to be safe. This also helps with dynamic navigation loading that cares if people are logged in or not, so doing it in the constructor makes sure that stuff is handled first before the navigation checks to see if someone is logged in.

When you want to add role-based authentication, so say only administrators have access to certain pages, I find it easiest to just create an isadmin($userid) function and so forth, then in your script you just run:

Code:
if ($this->users->isadmin($this->session->userdata('userid')))

I graduated to using ORM after my first commercial project with CI, but the principles I use are still the same and with similar methods - I just don't really use session itself very much, as it is now only responsible for holding id, username, and password and my constructor loads the corresponding user object and assigns it to $this->user.


Good luck on your coding, and it may seem daunting at first - but once you've done it the first time you see how simple sessions can be.

Oh, and storing sessions in the database is as easy as the manual says it is. Enter the config info as requested, make a table for your session data like the manual says, and magic - sessions stored in the db.
#4

[eluser]richzilla[/eluser]
Thanks for the help, this is really helping me. This my first real CI project so im still learning the ropes. The only problem i have now is that my logout function doesnt appear to be destroying the session:

Code:
function logout() {
            $this->session->unset_userdata('userId');
            $this->session->unset_userdata('userName');
            $this->session->unset_userdata('userGroup');
            $this->session->unset_userdata('loggedIn');
            $this->session->sess_destroy();
            $this->index();
        }

ive put a debug line on my login form, to check if the login variable is still set, and its coming back as yes. So i can only assume that somewhere its building the session with the old variables?

The index function called by the logout function is:

Code:
function __construct() {
            parent::controller();
            
            if ($this->session->userdata('loggedIn') == TRUE) {
                $this->_secure();
            }
        }
        
        //Load the login form, destroy any existing sessions
        function index() {
            $data = array (
            'pgTitle' => 'Issue Management - Start',
            'meta' => '<meta http-equiv="Pragma" content="no-cache" />
                       <meta http-equiv="Expires" content="-1" />
                       <meta http-equiv="Cache-Control" content="no-cache" />'
            );
            
            $this->load->view('header',$data);
            $this->load->view('site_view');
            $this->load->view('footer');
            $this->session->sess_destroy();
        }


i suspect my problem arises from my construct function, logging existing users back in, but as far as i understand, having unset everything and destroyed the session, it should be empty? so they couldnt be logged back in?

again any help would be appreciated. Thanks
#5

[eluser]BrianDHall[/eluser]
This is what I found deeply annoying with sessions - that tendency for them to be back again.

What I think is happening is first the constructor is called, logging them in. Then submit a page to logout, and the person is logged in again, and Then logout is called.

What I do now to avoid this is in my constructor I do this:

Code:
if ($this->input->post('logout') OR $this->uri->uri_string == "/logout")

You'd need to see what your logout uri string is to your code, and its a bit of a hack so there's better ways of doing it, I just didn't need to Smile

Then I run my logout function directly there. By the time they get down to logout page they are logged out, so then in my logout form I check to see if there was a post request to logout - and if there was then you can inform them they were logged out. But they are already logged out, so you don't have to do it again.

The hidden upside/caveat is you can log someone out (or in) from any page without directing them first to a special login/logout page. So for instance on a forum they could put in their login info on the same page as a post, hit post, and they would be logged in and then their post would be submitted (because they would get logged in before the post function was ever called). Stuff like that.

The trick with sessions seems to be that sess_destroy does not instantly destroy all session variables and the existance of the session. Next time the page loads there won't be an existing session and it's related variables, but in the script the behavior of sess_destroy wasn't what I expected it would be.
#6

[eluser]richzilla[/eluser]
The solution, it seems like the session data is being persisted for another request after it has been 'destroyed'. If i reload the page that the function redirects to all of the session variables are then destroyed. So if i redirect to another page, even if it automatically returns the user to their previous page, it clears out all of the session variables.

not a very pretty solution though....
#7

[eluser]n0xie[/eluser]
Your problem is here:

Code:
function logout() {
            $this->session->unset_userdata('userId');
            $this->session->unset_userdata('userName');
            $this->session->unset_userdata('userGroup');
            $this->session->unset_userdata('loggedIn');
            $this->session->sess_destroy();
            $this->index();
        }

You are loading the function index(). So the session is still active while you load this page. If you would redirect to the index then it should work as you expect.
#8

[eluser]BrianDHall[/eluser]
This is basically a problem with sessions themselves, I believe. I recalling having problems like this back when I learned sessions for the first time in PHP.

Try this:

Code:
function logout()
{
    $this->session->set_userdata('userId', '');
    $this->session->unset_userdata('userId');
    $this->session->sess_destroy();
}

Basically you can't assume that sess_destroy() or even unset will make session variables go away instantly - but changing their value works right away.

The variables are there up until the cookie is disassociated server-side and the browser requests a new page. On that new page the sessions will be new or gone, but not until then.

This just seems to be how sessions work. I don't like it, but you can get around it. When I want a session variable gone, really and truly gone, I set it to empty and unset it, and kill the session just for extra good measure.

When I automatically run validation at the start of every page, it checks for the variable I unset, such as userId, which I feel safe will be whatever it is supposed to be - whether they just logged out on this page access or not. I then just make sure that logout() gets called before anything else is done, else you'll get some functions thinking a person is logged in and later functions thinking they aren't and you'll wonder for hours what the hell is wrong.

This feels like a hack and a kludge, but it appears to be 'intended behavior' all the way around and its ok if you know that ahead of time and make sure you do things in the appropriate order.
#9

[eluser]nicholas.byfleet[/eluser]
Hey, one way of dealing with this is to use redirect() with a second parameter of 'refresh'. Hope this helps.
#10

[eluser]eightamrock[/eluser]
I found that CI was doing this to me as well same symptoms. I had a side rail that would show the users session data. Even after logout with sess_destroy() it still held the data.. but this snippet worked for me..

Code:
function logout(){
    if($this->session->userdata('loggedin') == true){
        $new_session_data = array(
            'user_id' => '',
            'first_name' => '',
            'username' => '',
            'loggedin' => '',
            'privs' => '',
            'expires' => '',
            'last_login' => ''
            );

        $this->session->set_userdata($new_session_data);
        $this->session->sess_destroy();
        return true;
    }else{

        return false;
    }
}




Theme © iAndrew 2016 - Forum software by © MyBB