We have a admin panel built in codeigniter, where two types of user get logged in (admin and super admin). Admin permissions are control by super admin. Admin permissions are stored in session at time of login. We are using codeigniter redis library for storing session data.
Now, the challenge is to update admin user session data without effecting admin login when permissions are changed by super admin.
if you want to do this on runtime i think with redis it shouldnt be really a problem
Create a pre Controller Hook where you check on every request if users session has been changed
since you use redis - you really don't need to use a DB Query in order to check it - just simply create an object which holds all changed users whose session have been changed and save it to redis
the hook could look like
class AppRefreshSession
{
private $ci;
public function __construct()
{
$this->ci = get_instance();
}
public function initialize()
{
if (!$this->isSessionValid())
{
//refresh users Session
}
}
private function isSessionValid()
{
$obj = $this->ci->cache->redis->get("ModifiedSessions_Object");
if ($obj->hasSessionModified())
{
return false;
}
return true;
}
}
And your modified sessions object should get filled with user ids or something like that whenever a superadmin changes the permission.
Save this object to redis and that should pretty much do what you want.
Related
Using Laravel 5.1 & 'file' Session Driver,
I'm trying to provide facility to user to track their sessions and invalidate them anytime they wish by keeping a record of their session_id within the database. With Database, I mean, I maintain a table called user_sessions which associates user_id with their session_id (obtained by Session::getId()).
So, to invalidate Session, I tried the following code,
$sessionId = Session::getId();
Session::setId($sessionId);
Session::invalidate();
and it works perfectly fine, for the case where, where user does not uses Remember Me feature.
For the case where user uses Remember Me feature, this above code does not work, So, I additionally, tried setting remember_token field to null as specified here in this answer, but with this, all sessions of the user get destroyed including the current one.
You can simply use
use Illuminate\Support\Facades\Session;
Session::forget('YOUR_SESSION_ID');
If you want to get the current session Id:
Session::driver()->getId();
I hope it helps
Sessions are meant to be short-lived. If you want something a bit more permanent you can use some sort of a long term user settings table.
Create a table user_settings:
id (PK), user_id(FK users table), settings(BLOB?), created_at, updated_at
Add a model:
class UserSetting extends Model {
public function user() {
return $this->belongsTo(User::class);
}
}
You can also associate the user with these via :
class User extends Model {
//...
public function settings() {
$this->hasMany(UserSetting::class);
}
}
You can then get all user sessions via:
User::find($u)->settings();
When a user logs in regularly or automatically via a remember token a Login event is fired.
You can listen to this in your event service provider:
\Event::listen(\Illuminate\Auth\Events\Login::class, function ($event) {
// Here you can load the last settings in the session if you want e.g.
session(['current_settings' => $event->user->settings()->latest()->value('id') ]);
// or you can just make a new entry:
$settings = new UserSettings();
$event->user->settings()->save($settings);
session(['current_settings' => $settings->id ]);
});
Note that you will have to manually persist things that need persisting instead of just putting them in the session.
So I have come across a problem.
1. I log into website using my user information on my desktop.
2. My sessions are set within the desktop.
3. I log into website using a smartphone. (Now there are 2 devices logged in.)
4. My sessions are set within smartphone.
5. I change my user information in user settings page using my desktop.
6. Database is updated.
7. Sessions are updated on desktop, but not on phone.
How do I fix it? Should I use CodeIgniter's database driver for sessions? Would that even matter?
Thanks.
I just created a session_refresh Model and autoloaded it. Hopefully this can scale and won't impact the server much.
protected $CI;
public function __construct()
{
$userdata = $this->session->userdata;
if (isset($userdata['uid']))
{
/*
* CONNECT TO DATABASE AND,
* CHECK IF MODIFIED TIMESTAMPS CHANGED
*/
$query = $this->db->get_where('users', array('uid' => $userdata['uid']));
$row = $query->row();
/*
* IF THE "MODIFIED" TIMESTAMP DIFFERS,
* UPDATE THE SESSION WITH THE NEW DATA.
*/
if ($userdata['modified'] !== $row->modified)
{
$this->CI =& get_instance();
$this->CI->load->model('user_model');
$this->CI->user_model->set_user_session($row);
}
}
}
I am developing a cms as my hobby and i got stuck on something....In my mysql db i have different classes of users:Admins, normal users, veterans, premium etc.....Is there a way to create a php file wich contains settings for each user class? And then to use a function or something to check if a certain user has the right to...create a page for example....
For the moment i am checking the users rights with sessions...
If($_SESSION['user_type']=='Admin'||$_SESSION['user_type']=='premium'){
//do stuff
}else if()......... {
// ..............
}
but i want something like that
check_user_right(user_name);
if ($can_create_page) == true{
do......}else{....}
First of all, you should know that you should be storing user information in the database. Then, when someone logs in and you verify the login, you can store his or her user ID in the session, and then to get all other user information, like user_type, you would query the database based on that ID. Not sure if you're doing that yet, but you should be if you aren't.
As far as user rights go, you have two options.
The OOP Way
This is the one I recommend. It entails creating a User class that encapsulates all of the logic for retrieving a user from the database and subsequently checking if that user has a specific right.
class User {
protected static $_rights = array(
'admin'=>array(
'create_page','remove_page', etc...
)
);
public static retrieve($id) {
// Call to your database or persistent storage to retrieve user info based on id
return new static($retrieved_user_data);
}
public function has_right($right) {
return in_array($right, static::$_rights[$this->user_type]);
}
}
The Non-OOP Way
This is much lower-level and may be better for you in the meantime. Basically you would create an array of rights per user level that you store in the same file as the function you use to check them. Then this function must in turn be included on every page you plan to use it.
E.g., say you put the function in a file called functions.php, and it looks like this:
$user_rights = array(
'admin'=>array('create_page','remove_page','edit_user',...),
'veteran'=>array('ban_user','edit_page'),
// Other rights here
);
function has_right($user_id, $right) {
global $user_rights;
// Retrieve information from persistent storage about the user
// which I'm assuming you will store in $user_info
return in_array($right, $user_rights[$user_info['user_type']]);
}
Then you should include this file on any other file that you want to check user rights, and then all you need is the user ID (Stored in the session after log in) and the user type, which you can get from the database or other persistent storage.
After the user has logged in I want to be able to save the userId for later use within the application. The only place in the application I retrieve the username is from the login form, through the login controller. However, that structure in my application is that the only thing that is passed to my master controller from the login controller is HTML.
Of course I could include the userId in a hidden field inside the HTML that's passed back to the master controller, but that seems too hacky.
So, is there a way that I can save a value (in this case the username) so that it's accessible from other classes/namespaces/functions whatever? I have read a bit about 'global', but haven't managed to get it work in my application.
from LoginController.php:
if ($loginView->TriedToLogin()){
$loginUsername = $loginView->GetUserName(); //Retrieved from form
$loginPassword = $loginView->GetPassword();
}
Upon login, you need to store your user token in a session.
See: http://au1.php.net/manual/en/features.sessions.php
Store user when logging in:
$_SESSION['user_id'] = 32; // fetch from your user provider
You can then write a class/function that utilises the session to check their login status and fetch their details when required.
Like so:
function getUserId()
{
return isset($_SESSION['user_id']) ? $_SESSION['user_id'] : false;
}
function isLoggedIn()
{
return isset($_SESSION['user_id']) && is_numeric($_SESSION['user_id']);
}
Then use anywhere in your application:
echo isLoggedIn() ? getUserId() : 'Anonymous';
Also, for great information on how to build an MVC framework, check out "Create your own framework... on top of the Symfony2 Components".
How about Sessions?
Session support in PHP consists of a way to preserve certain data
across subsequent accesses.
http://de2.php.net/manual/en/features.sessions.php
If it's only the username you want store, I would go with $_SESSION[].
It's not the most secure in a (shared) hosted environment, but it's so easy to call session_start(); first thing on pages using the stored data.
When my users are logged in I display their details (name, email) on the UI. When they update their profile, I would like to show the updated details, without requiring the user to log out and back in.
The UI details are retrieved from Zend_Auth via a view helper. Zend_Auth is storing the 'identity' details in a session.
How should I go about updating the details in the session?:
I was considering retrieving the user's login credentials from the database and using them to call Zend_Auth->authenticate() again. The problem is that I don't know the password, only it's md5 hash. I could consider a new method, reauthenticate(), which configured the adapter to bypass the md5 and salt, but this sounds laborious.
I was considering writing directly to the Zend_Auth session namespace, but this sounds like a recipe for trouble?
Have you come across a similar problem? How did you handle it?
Your ideas are much appreciated!
You can update Zend_auth identity for the currently logged user. Very simplified action that updates only username could be as follows:
public function editAction() {
// check if user is logged, etc, and then
// show the edit user form and process the data after submission.
$userForm = new My_Form_EditUser();
if ($this->getRequest()->isPost()) {
if ($userForm->isValid($_POST)) {
// process the submitted data,
// and when you are sure that everything went ok,
// update the zend_auth identity
$authData = Zend_Auth::getInstance()->getIdentity();
// this line would depend on the format of your
// identity data and a structure of your
// actual form.
$authData->property->nickname = $formData['user']['nickname'];
$this->_helper->FlashMessenger('Your data was changed');
return $this->_redirect('/');
}
}
$this->view->form = $userForm;
}
Hope this helps.
What I really want is a method on Zend_Auth::setIdentity($user).
But in the absence of such a method, I have used a hack in which I have create an auth adapter that always returns success and sets the identity to the same user object I would have created in a "real" auth adapter. Then I just call Zend_Auth::authenticate($adapter) with that adapter and it sets the identity internally.
Now, looking mosre closely at the internals of Zend_Auth::authenticate(), I see that what we could do is just:
Zend_Auth::getInstance()->getStorage()->write($user);
Here's how I solved the problem for the time being. Not sure yet if it's the best solution:
create a wrapper for Zend_Auth
include a getAuthAdapter($raw) method
configure the adapter differently, depending on the value of $raw
if (false === $raw) {
$this->_authAdapter->setCredentialTreatment('SHA1(CONCAT(?,salt))');
} else {
$this->_authAdapter->setCredentialTreatment();
}