Create One Session Per User - laravel-5

I'm trying to create 1 Session Per User in Laravel 5.4. How to configure 1 Session user in my laravel. this is my login controller.
I mean, If I login in Chrome. I can't login in Mozilla. So, I logout first in Chrome or Swap.
Login Controller
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Auth;
use Illuminate\Http\Request;
use Validator;
use DB;
use App\d_mem;
use Redirect;
use Session;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Adldap;
class LoginController extends Controller
{
protected $exceptionUsers = ['admin', 'user1', 'user2','bhandoko','ksoleh'];
public function index()
{
return view('auth.login');
}
public function welcome()
{
return view('welcome');
}
// use AuthenticatesUsers;
public function login(Request $req)
{
$user = d_mem::where('m_username',$req->username)->first();
if ($user && $user->m_password == sha1(md5('لا إله إلاّ الله') . $req->password)) {
$response = true;
}
if ($response) {
$usernm = $req->username;
Auth::login($user);
$ses = DB::select("SELECT d.m_id,
d.m_name as nama,
d.m_manager,
d.m_lead,
d.m_coordinator,
d.m_specialist,
d.m_email as email,
(SELECT dm.m_name from d_mem dm where dm.m_id=d.m_manager LIMIT 1) as manager ,
u2.m_name as lead,
u3.m_name as coor,
u7.m_name as spec,
u4.u_name as role,
u5.u_name as unit,
u5.u_id as unit_id,
u5.u_role as unit_role,
u5.u_flag as unit_flag,
u6.s_id as site_id,
u6.s_name as site_name
from d_mem d
LEFT JOIN d_mem u2 ON u2.m_id=d.m_lead
LEFT JOIN d_mem u3 ON u3.m_id=d.m_coordinator
LEFT JOIN d_mem u7 ON u7.m_id=d.m_specialist
LEFT JOIN d_unit u4 ON u4.u_id=d.m_access
LEFT JOIN d_unit u5 ON u5.u_id=d.m_unit
LEFT JOIN d_site u6 ON u6.s_id=d.m_site
where d.m_username = '$usernm'
");
// return json_encode($ses);
Session::put('id',$ses[0]->m_id);
Session::put('username',$req->username);
Session::put('name',$ses[0]->nama);
Session::put('unit',$ses[0]->unit);
Session::put('unit_id',$ses[0]->unit_id);
Session::put('unit_role',$ses[0]->unit_role);
Session::put('unit_flag',$ses[0]->unit_flag);
Session::put('email',$ses[0]->email);
Session::put('role',$ses[0]->role);
Session::put('coor',$ses[0]->coor);
Session::put('lead',$ses[0]->lead);
Session::put('spec',$ses[0]->spec);
Session::put('spec_id',$ses[0]->m_specialist);
Session::put('coor_id',$ses[0]->m_coordinator);
Session::put('lead_id',$ses[0]->m_lead);
Session::put('manager_id',$ses[0]->m_manager);
Session::put('manager',$ses[0]->manager);
Session::put('site',$ses[0]->site_id);
Session::put('site_name',$ses[0]->site_name);
$data = DB::table('d_mem')->where('m_username',$req->username)->update(['m_lastlogin'=>date('Y-m-d h:i:s')]);
return redirect(url('/home'));
}else{
return Redirect::back()->withErrors(['Wrong Username / Password !']);
}
}
use AuthenticatesUsers;
public function logout(Request $request)
{
Auth::logout();
$data = DB::table('d_mem')->where('m_username',Session::get('username'))->update(['m_lastlogout'=>date('Y-m-d h:i:s')]);
$request->session()->regenerate();
return redirect('/login')->with('info', 'You have successfully logged out');
}
}
Tell me step by step to implement One Session One login in Laravel 5.4.
Thanks

The solution I use for allowing one session per login is I use database for my sessions driver and on each login request I first remove all existing user sessions from the database table (using user_id column) and then create a new session for the user. In short user will be logged out of all other devices whenever he login from a new device.
To create sessions table use the following command
php artisan session:table
And in your login() method add the following line after authenticating user
DB::table('sessions')->where('user_id',$user->id)->delete();
Note: Since my application does not have many users so this solution works for me but if your application depends on a lot of users I would suggest using in-memory storage like memcache or redis as your session drivers.

Related

laravel manually authenticate user

I want to manually login a user in laravel 8. The problem is that authentication succeeds, but the authenticated user is not stored in the session(or the session is not updated). I use the method given in de docs.
My loginController has two methods: 1) showing the login form and 2) performing the login
<?php
namespace App\Http\Controllers;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function login(){
return view('auth/login');
}
public function validateLogin(LoginRequest $request){
if (Auth::attempt(['email'=>$request->email, 'password'=>$request->password])) {
$request->session()->regenerate();
return redirect()->to('/');
}
return back()->withErrors(['credentials' => 'Deze gegevens zijn niet bekend!']);
}
}
The controller redirects indeed to / , so the user is authenticated but after the redirect the autenticated users is unavailable, so somehow it is not stored in the session.
Does anyone know how to solve this?
I removed the id from the User model as I wanted to use the e-mailadress as the primary key. This violated the Authenticable trait so the session was not updated.
The usermodel needed the following function to replace the id with the email:
public function getKeyName(){
return 'email';
}
The same can be accomplished with:
protected $primaryKey = 'email';
public $incrementing = false;

Laravel override Login controller, login(). How do i retrieve logged in user data if i overwrite the login controller. I tried to get auth() data

I used laravel like 4 years ago. Had to work on a project on laravel and tried using my own authentication methods but mybad forgot there was already inbuilt better security authentication. I understand if my question seem to be basic.
As you can see the commented line "$userID = Auth::user()->userID;" the auth() is null therefore, userID cannot get its id from null. I am unable to get user session data in any other controllers as well.
Any kind of help or suggestions is appreciated.
P.S. i have used the default login and registration inbuilt function only required function like login is override code. I am using laravel v 4.2.3. I tried passing the userid as url parameter but then discarded it as inbuilt session data makes it more secure and easier
the login function of my controller looks like this
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
protected function login(Request $request){
$user = new User(); //my model User
$result=$user->login($request); //result has the id of the user
if ($result) {
//$userID = Auth::user()->userID;
return redirect()->route('homepage');
}else{
return redirect()->route('login');
}
}
}
model for user login()
//Auth user then let them login
public function login($request){
$email = $request->input('email');
$password = $request->input('password');
$result=DB::table('users')
->where('email', $email)
->where('password', $password)
->get();
return $result;
}
My Routes.. its default route of "Auth::routes();"
Route::get('/homepage/{userID?}', function($userID = null){
return view('index', ['userID' => $userID]);
})->name('homepage');
Route::get('/evaluate/{userID?}', function ($userID = null) {
return view('evaluate', ['userID' => $userID]);
})->name('evaluate');
I installed a fresh new laravel and tried my code again and somehow it worked. Must have made some errors when trying to override the codes. Thank you

How to get user's sessions when using the database session driver?

I want to check the logged-in user and the user_id column in Session table and also count the result. So I tried to use this
$login = Session::where('user_id', Auth::id())->count();
But it returned this error
Call to undefined method Illuminate\Session\Store::where()
You have 2 options:
Use DB facade:
use Illuminate\Support\Facades\DB;
$login = DB::table('sessions')->where('user_id', Auth::id())->count();
define a new Session model and use it to count logins:
php artisan make:model Session
$login = \App\Session::where('user_id', Auth::id())->count();
By this way, you can also define a sessions relationship
on user model:
class User extends Authenticatable
{
/**
* Get the sessions of the user.
*/
public function sessions()
{
return $this->hasMany('App\Session');
}
}
and call it like this:
$login = Auth::user()->sessions()->count();

Laravel middleware for control user access to datas

I'm using this structure of user levels:
Company Owner
- Group Manager
-- Unit Manager
---Employee
I need to control users to access the datas in the database. Employee can access only that datas what he stored. The unit manager can access his own datas and datas of his emplyee too. Group manager can access to entire group's datas. And the company owner can acceess to everything.
I have some controllers like this:
class ClientController extends Controller
{
public function index()
{
return Client::all();
}
// ...
}
What is the best practice in Laravel to control access to datas (not the controller) in some controllers, but not everywhere? Is here a good implementation for this issue?
You can create a middleware for each role, then in your web.php file, use route groups to assign access to the routes that the users can access. So for a route that both employee and unit manager can access, you pass the two middleware, for those that only group manager can access, you just pass group manager.
Route::group(['middleware' => ['auth', 'group-manager','unit-manager']],
function() {
Route::get('client','ClientController#index');
});
In Route. One good place for all middleware.
Route::get('/', function () { ... })->middleware('web');
middleware is the right place for access control. For group middleware you can use by this format
Route::group(['middleware' => ['role:Company Owner']], function() {
Route::get('/', 'AdminController#welcome');
Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController#manageAdmins']);
});
Route::group(['middleware' => ['role:Employee']], function() {
Route::get('/', 'AdminController#welcome');
Route::get('/manage', ['middleware' => ['permission:manage-admins'], 'uses' => 'AdminController#manageAdmins']);
});
For single route
Route::put('post/{id}', function ($id) {
//
})->middleware('role:Employee');
You can use a package for user role base access control
https://github.com/Zizaco/entrust
Maybe the question wansn't clear enough, but I found a solution:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Auth;
use App\User;
class DataAccessScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
// find the actual user
$user_id = Auth::user()->id;
$user = User::find( $user_id );
// get all employees
$employees = $user->allEmployeeFlatten();
// get only the employee's ids
$user_ids = $employees->pluck('id');
// add current user's id too
$user_ids->push( $user_id );
// add the condition to every sql query
$builder->whereIn('user_id', $user_ids);
}
}
Here is the User model's allEmployeeFaletten() function:
public function allEmployeeFlatten() {
$employees = new Collection();
foreach ( $this->employee()->get() as $employee ) {
$employees->push( $employee );
// run only if the user is on a leader level
if ( $employee->user_role_id != 5 ) {
$employees = $employees->merge( $employee->allEmployeeFlatten() );
}
}
return $employees;
}
This scope add a condition to all SQL queries every time I use the scope.

Laravel custom login losses Session after redirect

i need a two way Login. First check database one if user exists and if not check database two.
So i build a custom Login Controller:
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Redirect;
use App\Http\Controllers\Controller;
class CustomLoginController extends Controller
{
public function login(Request $request)
{
if($request->email) {
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect()->intended('/');
} else {
DB::setDefaultConnection('otherdb');
if (Auth::attempt($credentials)) {
// The Login credentials will be found and user will be logged in
but after Redirect to home user isn't logged in anymore.
return redirect()->intended('/');
} else {
return redirect()->to('/login')
->withInput($request->only($credentials['email'], 'remember'))
->withErrors([
'email' => Lang::get('auth.failed'),
]);
}
}
} else {
return view('auth.login');
}
}
}
After i changed the database Connection with "DB::setDefaultConnection('otherdb');", the second login works but after Redirect to any page user isn't logged in anymore.
What am I doing wrong?
Any ideas?
Laravel trying to find a user in DB in every request. So after redirect there in no user in your default database. DB connection doesn't stored in session.
I think you need to create a custom auth guard with another user model like
class OtherUser extends Eloquent
{
protected $connection = 'otherdb';
}
and work with it.

Resources