I am using Tank Auth for user management in my CI 1.7.3 App. Everything is working fine but I'm trying to set a flash_message to be displayed when the user logs out. The problem is the $this->tank_auth->logout(); function destroys the session. I have modified the logout function in the Tank Auth library to look like:
function logout() {
$this->delete_autologin();
// See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
$user_session_data = array('user_id' => '', 'username' => '', 'status' => '');
$this->ci->session->set_userdata($user_session_data);
$this->ci->session->unset_userdata($user_session_data);
}
It was previously
function logout()
{
$this->delete_autologin();
// See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
$this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
$this->ci->session->sess_destroy();
}
In My controller I have
function logout(){
if ($this->tank_auth->is_logged_in()) { // logged in
$this->session->set_flashdata('status_message', $this->lang->line('auth_message_logged_out'));
$this->tank_auth->logout();
redirect('');
}
}
If I remove the $this->tank_auth->logout(); function the message shows fine. I'm sure it's a simple session problem
If you try to set flashdata while using a database in the same request after you call sess_destroy(), it won't work (because there is no session to append the flashdata to).
To fix this problem, add $this->ci->session->sess_create(); after the call to sess_destroy(). This works because you're re-creating the session before trying to append data to it. This is the only way to use flashdata after a sess_destroy() if you're using sessions in a database.
The sess_destroy() function destroys also the session flash variables used to pass the message.
U already answered your question, in the library logout() function, you need to replace
$this->ci->session->sess_destroy();
with
$this->ci->session->unset_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
This will not completely destroy the session, only the user data used for login, so I recommend instead, to modify the logout() function in the controller and show the message manually, by passing it to a view.
While this is a workaround, it might do the trick for you...
wherever you're displaying these, I'll be assuming you're checking in the view so...
<? if ($this->session->flashdata('status_messege'): ?>
<p><?= $this->session->flashdata('status_message') ?></p>
<? endif; ?>
you COULD add an elseif to that and check for the referrer being your logout function...
<? if ($this->session->flashdata('status_messege'): ?>
<p><?= $this->session->flashdata('status_message') ?></p>
<? else if ($this->agent->referrer() == site_url('path/to/logout'): ?>
<p><?= $this->lang->line('auth_message_logged_out') ?></p>
<? endif; ?>
A bit of a hackish way to overcome this issue, but probably a way nonetheless.
Related
I am facing some weird issue of session variable getting reset on action redirect.
I am using Codeigniter and redirecting to dashboard action after login, I am getting data in login action after verifying credentials with DB, but when I use redirect() to redirect to dashboard, session variables gets vanished.
Admin.php
<?php class admin extends CI_Controller
{
function login()
{
$login = $this->Admin_model->login($this->input->post()); // <-- verify data and set to session
if($login)
{
$this->session->set_flashdata("success","Logged in Successfully");
var_dump($_SESSION); // <-- able to fetch data from session
// exit();
redirect("admin/dashboard");
}
else
{
$this->session->set_flashdata("error","Invalid Credentials!! Please Try Again!!");
redirect("admin");
}
}
function dashboard()
{
var_dump($_SESSION); // <-- session data is vanished and not able to get userdata('id')
exit();
if($this->session->userdata('id') != '')
{
$data['active_tab'] = "dashboard";
}
else
{
redirect("admin");
}
}
?>
Admin_model.php
<?php Class Admin_Model extends CI_Model
{
function login($data)
{
$user = $this->db->get_where("users",array("username" => $data['username'],
"password" => md5($data['password']),
"is_active" => "1")
)->row_array();
if(!empty($user))
{
$this->set_user_session($user);
return true;
}
else
{
return false;
}
}
function set_user_session($login)
{
$arr = array();
$arr["id"] = $login["id"];
$arr["username"] = $login["username"];
$this->session->set_userdata($arr);
}
?>
Tried this in xampp and wamp, all browsers but still the issue remains the same, any help would be grateful.
Which version of CodeIgniter are you working with? You can try the following steps.
Go to system/libraries/Session/Session.php
Comment session_start() by adding //. We want to relocate the sessionn_start().
Find (using ctrl + f) a comment that says Security is king. Comment out all the line under that comment until the end of the function. In my case I commented out the line number 315 - 320.
on line number 282 change this line ini_set('session.name', $params['cookie_name']); to ini_set('session.id', $params['cookie_name']);
comment out following lines
line 108 //session_set_save_handler($class, TRUE);
line 290-296
// session_set_cookie_params(
// $params['cookie_lifetime'],
// $params['cookie_path'],
// $params['cookie_domain'],
// $params['cookie_secure'],
// TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
// );
line 305 //ini_set('session.gc_maxlifetime', $expiration);
Go to the main index.php, it is the first index.php and located in the same directory with the sub-directories 'application', 'system', 'user_guide', etc.
Put session_start() right after < ?php
Hope this can help you....
You have to use this->session->set_userdata() for setting the session. this->session-> set_ flashdata() is used for setting flash messages which are removed after next action.
The new versions of the browsers might be destroying the session because of the new cookie policy.
References
https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Whenever the cookie is required to be sent to server, the browser sees the SameSite attribute to decide if the cookie to be sent to server or blocked. For user actions, it is sent to the server but for auto-redirects, it doesn't if SameSite is set to 'Strict' or 'Lax' (Lax is going to be the default value now).
Solution:
The cookie attribute SameSite can be set to 'None' along with specifying the 'Secure' attribute to 'true'. Setting 'Secure' attribute to 'true' would require your site to run on https. Sites running with http:// protocol will not be able to set 'Secure' cookie.
Please set the 'HttpOnly' attribute to 'true' for making it accessible for http requests to the server only.
In PHP, it can be achieved as below
session_set_cookie_params(0, '/PATH/; SameSite=None', <COOKIE_DOMAIN>, true, true);
I am trying to unset my current logged in user's session.It's working fine if i am doing normal login but when i use remember me settings using cookies it's not being destroy.
My code for set the session and cookie is
public function login() {
if(isset($this->session->userdata['username']) || isset($_COOKIE['user_id'])){
$this->load->model('User');
$p_uid = $this->User->user_login($_COOKIE['user_id'], $_COOKIE['password']);
redirect(base_url() . "dashboard");
}else{
$this->form_validation->set_rules('user_id', 'User ID', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == FALSE) {
$this->load->view('login/login');
} else {
$user_id = $this->input->post('user_id');
$password = $this->input->post('password');
$this->load->model('User');
$p_uid = $this->User->user_login($user_id, $password);
//var_dump($p_uid);
if ($p_uid) {
if(isset($_POST['remember_me'])){
setcookie("user_id",$user_id,time()+86400*30);
setcookie("password",$password,time()+86400*30);
}
redirect(base_url() . "dashboard/");
} else {
$data=array(
"error"=>"Wrong Userid Or Password"
);
$this->load->view('login/login',$data);
}
}
}
}
And My logout Function is:
public function logout(){
$this->load->helper('cookie');
delete_cookie("user_id");
delete_cookie("password");
$this->session->unset_userdata("username");
$this->session->sess_destroy();
redirect(base_url());
}
Where i am doing mistake. please help. Thanks
First of all, your remember-me mechanism is seriously flawed. See Implementing Secure User Authentication in PHP Applications with Long-Term Persistence.
I don't understand how your login works. You are checking if username is set in session, then are using cookies to perform login. I guess you've made it work as the first part of || always fails since $this->session->userdata['username'] will never be set. The correct way to access username from session would be:
$_SESSION['username']
OR
$this->session->userdata('username')
OR
$this->session->username
Finally, make sure the cookies are actually being deleted by inspecting your requests in network tab. Codeigniter deletes cookies by setting a negative expiration time of around a day, see if this is the case in your version of Codeigniter. For best results, just set the cookie again with large negative expiration time, and instead of checking if cookie is set, check if cookie is !empty.
I've faced the same issue a while ago. I was trying all methods which were possible. But I failed. Finally I found the solution with ob_start and ob_clean . Logout should be like this:
class controllerName extends CI_Controller
{
function __construct()
{
parent::__construct();
ob_start();
$this->load->library('Session');
$this->load->helper('cookie');
}
public function logout()
{
$this->load->driver('cache');
$user_id = array(
'name' => 'user_id',
'value' => '',
'expire' => '0',
'domain' => '.localhost',
'prefix' => ''
);
delete_cookie($user_id);
$this->session->sess_destroy();
$this->cache->clean();
ob_clean();
redirect(base_url());
}
}
To prevent browser back button previous page load, you should do something like this
$sess = $this->session->userdata('username');
if(empty($sess))
{
$this->session->set_flashdata('error', 'Session has Expired. Please login');
redirect('loginController/method');
}
else
{
# success.
# continue the normal code here
}
FYI: This should be added in every function or being used by a constructor to do it.
NOTE : Don't add password in cookie. Read - php cookie injection vulnerability?
To unset single element from session array:
$this->session->unset_userdata('some_name');
You can pass an array of keys to unset multiple values:
$array_items = array('username' => '', 'email' => '');
$this->session->unset_userdata($array_items);
public function check_admin_login()
{
$admin_email_address=$this->input->post('admin_email_address',true);
$admin_password=$this->input->post('admin_password',true);
$this->load->model('admin_model','a_model');
$result= $this->a_model->check_admin_login_info($admin_email_address,$admin_password);
// echo '<pre>';
// print_r($result);
// exit();
$sdata=array();
if($result)
{
$sdata['full_name']=$result->admin_full_name;
$sdata['admin_id']=$result->admin_id;
$this->session->set_userdata($sdata);
//$sdata[]
redirect('super_admin');
}
else{
$sdata['message']='Your User Id / Password Invalide !';
$this->session->set_userdata($sdata);
$this->load->view('admin/admin_login');
}
}
for login and for logout
public function logout()
{
$this->session->unset_userdata('full_name');
$this->session->unset_userdata('admin_id');
$sdata=array();
$sdata['message']='You are Successfully Logout !';
$this->session->set_userdata($sdata);
redirect('admin');
}
This will happen when login page in http or localhost then codeigniter create session for http or locahost.
when we are trying get session in https://www.example.com or http://[::1]/ then the session will not added for these type of urls..
try to use one type of url pattern in website
For delete cookie
delete_cookie('name', $domain, $path);
For delete/destroy sesstion
$this->session->sess_destroy();
To destroy a particular session
$this->session->unset_userdata('name');
For multiple items
$items = array('item-name1' => '', 'item-name2' => '');
$this->session->unset_userdata($items);
Edited:
I am too sad that this question was downvoted, I was stuned by this for many hours.I wish there are a lovely alchemist who can make me back from debuff condition.
I am using codeigniter,I think the problem is when the new session (the session with flash message) is set, the session id (as a cookie) does not send to client, so after redirect to other pages, a fresh new session is created.
There is a problem in my log out function. The logic is simply click "log out", redirect to index page with a flash message--You have been log out.
After inspect, I found these things:the old session is clear with no problems, the new session is created before redirection, the new session do has flash message. Then the strange things comes, when redirected to index, a fresh newer session is created. But, If I do not run redirection after adding flash message, and click browser's refresh, then go to index manually, the session with flash message will be there and displayed perfectly.
I also found before redirection or refresh browser, though the session is recreated, there is no session id in my cookies. The refresh action sends session id to my cookies.
I hope I made the question clear. Thank you.
//auth controller
public function logout()
{
$this->my_auth_lib->logout();
$this->session->set_flashdata('alert','You have been logged out!');
redirect('index');
}
//my_auth_lib
public function logout()
{
return $this->session->sess_destroy();
}
// session library sess_destory method
public function sess_destroy()
{
// get session name.
$name = session_name();
if (isset($_COOKIE[$name])) {
// Clear session cookie
$params = session_get_cookie_params();
setcookie($name, '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
unset($_COOKIE[$name]);
}
$this->sess_create();
}
//session library sess_create method
public function sess_create()
{
$_SESSION[$this->sess_namespace] = array(
'session_id' => md5(microtime()),
'last_activity' => time()
);
// Set matching values as required
if ($this->_config['sess_match_ip'] === true) {
// Store user IP address
$_SESSION[$this->sess_namespace]['ip_address'] = $this->ci->input->ip_address();
}
if ($this->_config['sess_match_useragent'] === true) {
// Store user agent string
$_SESSION[$this->sess_namespace]['user_agent'] = trim(substr($this->ci->input->user_agent(), 0, 50));
}
$this->store = $_SESSION[$this->sess_namespace];
}
Try putting an
exit;
statement in the line right after the redirect
Got the idea from here
PHP: session isn't saving before header redirect
I use two different sessions for admin and user,and I want to destroy each session separately but when I destroy one session using $this->session->sess_destroy(); it destroys both sessions. Please help me.
$admin_data = array (
'admin_email' => $this->input->post('admin_email'),
'is_admin_logged_in' => 1
);
$this->session->set_userdata($admin_data);
redirect('admin_profile');
public function admin_profile() {
if ($this->session->userdata('is_admin_logged_in')){
$this->load->view("view_admin_profile");
}
else {redirect('login');}
}
public function logout() {
$this->session->unset_userdata($admin_data);
redirect("login");
}
you can use $this->session->unset_userdata('name of session');
for more info check the user-guide
https://www.codeigniter.com/user_guide/libraries/sessions.html
You can use :-
$this->session->unset_userdata('some_name');
unset_userdata() can be used to remove it, by passing the session key
For e.g :
If your admin session name is 'admin_id' and user session id is 'user_id' then you can seperately destroy both the session like this :-
$this->session->unset_userdata('admin_id'); // for admin
$this->session->unset_userdata('user_id'); // for user
To destroy the session in codeigniter simply do this;
function logout() {
$this->session->sess_destroy();
}
If i uncomment this code, i get blank page at site. If i comment this, site works.
Here is my exit code (auth by sessions):
function exit($action='') {
if ($action == "true") {
echo "Exit.";
return;
}
$login = $this->session->userdata('username');
if ($login == NULL) {
redirect('/blog/login/', 'location', '301');
}
$array_itmes = array('username' => "$login");
$this->session->unset_userdata($array_items);
redirect('/blog/exit/true/', 'location', '301');}
after normal login:
$newdata = array('username' => "$name");
$this->session->set_userdata($newdata);
in other actions i using:
$login = $this->session->userdata('username');
if ($login !== NULL) {
echo $login;
}
and I get my username. where is an error in first code? i`m from Russia, so sorry for bad English.
Just replace it with $this->session->sess_destroy();
$array_val = array('userid' => '','username' => '', 'email' => '');
$this->session->unset_userdata($array_val);
This is remove individual session details.
Anton's answer will destroy whole session at once. If you would want to delete entire session data use this like Anton said,
$this->session->sess_destroy();
But if you would want to only destroy specific user data use below,
$this->session->unset_userdata('user_name');
Hope this helps, thanks!!
Happy coding!!
To clear the current session (for example, during a logout), you may simply use either PHP’s session_destroy() function or the sess_destroy() method. Both will work in exactly the same way:
session_destroy();
// or
$this->session->sess_destroy();
you can also use
session()->destroy();
it clears the session buffer so you get the logging out effect.