Session in middleware don't working - laravel

I'm storing a value in session in my middleware:
but when I refresh or go to new page the sessions is null.
what I do wrong?
class WorkflowContextMiddleware
{
/**
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|mixed
*/
public function handle(Request $request, Closure $next)
{
$types = $request->input('types', []);
foreach ($types as $type => $context) {
$request->session()->put("somekey.contexts.{$type}", $context);
$request->session()->save();
}
return $next($request);
}
}
route:
Route::group([
'prefix' => LaravelLocalisation::setLocale(),
'middleware' => ['web','localise','localeSessionRedirect']
], function () {
Route::get('/', function() {
(new \Illuminate\Support\Debug\Dumper)->dump(\Session::get('somekey'));
});
});
route provider:
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to the controller routes in your routes file.
*
* In addition, it is set as the URL generator's root namespace.
*
* #var string
*/
protected $namespace = 'Arcanine\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* #param \Illuminate\Routing\Router $router
* #return void
*/
public function boot(Router $router)
{
//
parent::boot($router);
}
/**
* Define the routes for the application.
*
* #param \Illuminate\Routing\Router $router
* #return void
*/
public function map(Router $router)
{
$router->group(['namespace' => $this->namespace], function ($router) {
require app_path('Http/routes.php');
});
}
}
Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Workflow\Http\Middleware\WorkflowContextMiddleware::class,
],

In order for your session to work, wrap all your routes within:
Route::group(['middleware' => 'web'], function () {
...
});

Remove web middleware from route group if you're using 5.2.27 and higher.
The thing is all routes in web.php are already using web middleware and adding it manually will cause problems with sessions.

Related

Need help fixing a Laravel PageController class error

Whenever I try to click a button on localhost site such as the manage users
I get the error:
Target class
[App\Http\Controllers\App\Http\Controllers\Admin\PagesController] does
not exist.
I tried a lot of different things to try fix it and I just don't know how to fix it. I asked on forums like this too and I none of the suggestions I was given helped.
Here is the code for my page controller:
<?php
namespace App\Http\Controllers\Admin;
use Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\WorkWithPage;
use App\Models\Page;
use Illuminate\Http\Request;
class PagesController extends Controller
{
public function __construct() {
$this->middleware('admin');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
if (Auth::user()->isAdminOrUser()) {
$pages = Page::paginate(5);
} else {
$pages = Auth::user()->pages()->paginate(5);
}
return view('admin.pages.index', ['pages' => $pages]);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
return view('admin.pages.create')->with(['model' => new Page()]);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(WorkWithPage $request)
{
//
Auth::user()->pages()->save(new Page($request->only([
'title','url','content'])));
return redirect()->route('pages.index')->with('status', 'The page has been created.');
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Page $page
* #return \Illuminate\Http\Response
*/
public function edit(Page $page)
{
if(Auth::user()->cant('update', $page)) {
return redirect()->route('pages.index');
}
return view('admin.pages.edit', ['model' => $page]);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\Page $page
* #return \Illuminate\Http\Response
*/
public function update(WorkWithPage $request, Page $page)
{
if(Auth::user()->cant('update', $page)) {
return redirect()->route('pages.index');
}
$page->fill($request->only([
'title','url','content']));
$page->save();
return redirect()->route('pages.index')->with('status', 'The page has been updated');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Page $page
* #return \Illuminate\Http\Response
*/
public function destroy(Page $page)
{
if(Auth::user()->cant('delete', $page)) {
return redirect()->route('pages.index');
}
}
}
Here is the code for my web.php route:
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/admin', function() {
return view('admin.index');
})->middleware('admin');
Route::resource('/admin/pages', \App\Http\Controllers\Admin\PagesController::class, ['except' => [
'show'
]]);
Route::resource('/admin/users', \App\Http\Controllers\Admin\UsersController::class, ['except' => [
'create','store','show'
]]);
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/home', 'HomeController#index')->name('home');
Add the controllers at the beginning of your web.php routes file
use App\Http\Controllers\Admin\PagesController;
use App\Http\Controllers\Admin\UsersController;
Then define your route as
Route::prefix('admin')->group(function () {
Route::resource('pages', PagesController::class);
Route::resource('users', UsersController::class);
});
Maybe the error is because you forgot to put [] when calling your controller.
Modify this:
Route::resource('/admin/pages', \App\Http\Controllers\Admin\PagesController::class, ['except' => [
'show'
]]);
Route::resource('/admin/users', \App\Http\Controllers\Admin\UsersController::class, ['except' => [
'create','store','show'
]]);
by:
Route::resource('/admin/pages', [\App\Http\Controllers\Admin\PagesController::class], ['except' => [
'show'
]]);
Route::resource('/admin/users', [\App\Http\Controllers\Admin\UsersController::class], ['except' => [
'create','store','show'
]]);
You have to go into your the app/Providers/RouteServiceProvider.php file and comment this line:
protected $namespace = 'App\\Http\\Controllers';
//should be
//protected $namespace = 'App\\Http\\Controllers';
If you do so, you'll be able to use this notation your are using when declaring your routes:
Route::get('something', [\Fully\Qualified\Namespace::class, 'method']);
However, these kind of routes, will not work anymore:
Route::get('/home', 'HomeController#index')->name('home');
// since there are no more default namespace, you must use
// Route::get('/home', '\App\Http\Controllers\HomeController#index');
// or
// Route::get('/home', [\App\Http\Controllers\HomeController::class, 'index']);
You have to choose which route declaration style you use and stick to it for all routes.
Nowadays, Route::get('something', [\Fully\Qualified\Namespace::class, 'method']) is what you should use.

Custom Middleware Not working when using Sanctum

I am using Dynamic database for my laravel API Project. I am doing that with a middleware. When I use auth:sanctum in api rout middleware not working. But normally its working fine.
Route> api.php
Route::group(['middleware'=>'database'], function() {
Route::group(['namespace' => 'App\Http\Controllers\Admin', 'middleware' => ['auth:sanctum']], function () {
Route::get('dashboard', function () {
return "conncted sucessfully to database ".\DB::connection()->getDatabaseName();
});
});
});
Middleware > Database.php
namespace App\Http\Middleware;
use Closure;
use App\Models\SoftClient;
class Database
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$route = app('router')->getRoutes()->match($request);
$prefix = $route->action['name'];
$s_client = SoftClient::where('url', $prefix)->first();
\Config::set('database.connections.multidomain.host', $s_client->db_host );
\Config::set('database.connections.multidomain.database', $s_client->db_name );
\Config::set('database.connections.multidomain.username', $s_client->db_username );
\Config::set('database.connections.multidomain.password', $s_client->db_password );
\DB::reconnect('multidomain');
return $next($request);
}
}
'database' => \App\Http\Middleware\Database::class,
I add this to Karnel.php
When I send request to dashboard I got bellow error. If I not use auth:sanctum It's working fine.
Illuminate\Database\QueryException: SQLSTATE[HY000] [1045] Access denied for user ''#'localhost' (using password: NO)
auth sanctum is used to authenticate user. Maybe you are directly accessing the routes with authenticating user.
when you check the routes with "php artisan route:list", do you see the middleware you configured with the route?
I had a similar problem, where route:list pointed me to the fact that the middleware I defined with the group wasn't actually used, and in the end I dropped the "group" and just defined the routes individually. A bit cumbersome but it worked.
if your goal is to use laravel sanctum for dynamic database connection then i use this method and it works
step 1 : copy this file Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful to our middlewear and then modify duplicate this file like this
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Pipeline;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\App;
class EnsureFrontendRequestsAreStateful
{
/**
* Handle the incoming requests.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return \Illuminate\Http\Response
*/
public function handle($request, $next)
{
$this->changeDatabaseConnection($request);
$this->configureSecureCookieSessions();
return (new Pipeline(app()))->send($request)->through(static::fromFrontend($request) ? [
function ($request, $next) {
$request->attributes->set('sanctum', true);
return $next($request);
},
config('sanctum.middleware.encrypt_cookies', \Illuminate\Cookie\Middleware\EncryptCookies::class),
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
config('sanctum.middleware.verify_csrf_token', \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class),
] : [])->then(function ($request) use ($next) {
return $next($request);
});
}
protected function changeDatabaseConnection($request)
{
$encodeCc = $request->input('cc');
$cc = json_decode(base64_decode($encodeCc));
if ((!empty($cc) && $cc != 'axiasolusi')) {
$compCode = $cc;
if (App::environment() === 'local') {
$compCode = 'ess-' . $compCode;
}
} else {
$compCode = env('DB_DATABASE');
}
Config::set('database.connections.' . env("DB_CONNECTION") . '.database', $compCode);
}
/**
* Configure secure cookie sessions.
*
* #return void
*/
protected function configureSecureCookieSessions()
{
config([
'session.http_only' => true,
'session.same_site' => 'lax',
]);
}
/**
* Determine if the given request is from the first-party application frontend.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
public static function fromFrontend($request)
{
$domain = $request->headers->get('referer') ?: $request->headers->get('origin');
if (is_null($domain)) {
return false;
}
$domain = Str::replaceFirst('https://', '', $domain);
$domain = Str::replaceFirst('http://', '', $domain);
$domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";
$stateful = array_filter(config('sanctum.stateful', []));
return Str::is(Collection::make($stateful)->map(function ($uri) {
return trim($uri) . '/*';
})->all(), $domain);
}
}
step 2 : change karnel like this
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // original
\App\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
and last step : change route api
Route::middleware('change.database')->group(function () {
Route::post('/verify-company-code', 'Api\Web\Auth#verifyCompanyCode');
Route::post('/verify-user-account', 'Api\Web\Auth#verifyUserAccount');
Route::post('/verify-user-pin', 'Api\Web\Auth#verifyUserPin');
Route::post('/forgot-password', 'Api\Web\Auth#forgotPassword');
Route::post('/reset-password', 'Api\Web\Auth#resetPassword');
});
Route::middleware(['auth:sanctum'])->group(function () {
Route::post('logout', [Auth::class, 'logout']);
Route::post('logout-all', 'Api\Web\Auth#logoutAll');
});
});

The custom middleware is not working in the controller (Laravel)

I did a custom middleware to handle the auth api token and I call this middleware in the controller, but it's not working I added dd('') inside the middleware to see if it displays anything and it did not worked.
My middleware is:
<?php
namespace App\Http\Middleware;
use Closure;
use App\ApiUser;
class ApiAuth
{
/**
* Run the request filter.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $var)
{
dd('If I put this dd it does not display anything');
$api_user_count = ApiAuth::where('api_token', $var)->count();
if($api_user_count == 0)
{
abort(403, "Auth failed")
}
return $next($request)
}
}
My controller is, how you can see I am sending a parameter to the middleware:
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->middleware('apiauth:'.$request->api_token);
$transaction = new Transaction;
$transaction->folio = $request->folio;
$transaction->dte_code = $request->dte_code;
$transaction->cashier = $request->cashier;
$transaction->amount = $request->amount;
if($transaction->save())
{
return response()->json('Ok', 201);
}
else
{
return response()->json('Error', 400);
}
}
I put the middleware in the path App\Http\Middleware\ApiAuth.php
I put the middleware in the kernel.php like this:
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'apiauth' => \App\Http\Middleware\ApiAuth::class, // THIS IS THE MINE
];
The weird thing is that it does not display any error, it's like it does not exist so I wonder what it's wrong with this?
Thanks!
instead of calling the middleware manually from your controller method you can register the middleware to apply only for that one method
public function __construct()
{
$this->middleware('apiauth')->only(['store']);
}
then you can extract the api_token from $request
$api_user_count = ApiAuth::where('api_token', $request-> api_token)->get()->count();

How to setup two route groups using middleware in Laravel 5.4

I'm setting up a web application in which I would like to distinguish two route groups. Both groups work as expected on their own, but when combined one of them fails. I've checked documentation on L5.4 website and followed instructions. After a whole day of digging decided to ask you.
Here is my routes/web.php file:
Route::group(['middleware' => ['auth']], function () {
Route::group(['middleware' => ['medewerker']], function () {
Route::get('/urencorrectie','UrenRegelsController#urencorrectie');
});
Route::group(['middleware' => ['officemanager']], function () {
Route::get('/', 'DashboardController#index');
Route::post('/', 'DashboardController#index');
Route::get('/profile', function(){
return view('profile');});
});
});
Auth::routes();
Route::get('/home', 'HomeController#index');
In order to enable roles I addes a column Rolid to the user model. Rol 1 is officemanager and role 3 is employee.
Then in the subsequent middleware we find employee.php:
namespace App\Http\Middleware;
use Closure;
use Auth;
class Employee
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user()->Rolid=='3')
{
return $next($request);
}
else
{
return redirect('/home');
}
}
}
The Middleware officemanager.php file contains:
namespace App\Http\Middleware;
use Closure;
use Auth;
class Officemanager
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user=Auth::user();
if(Auth::user()->Rolid=='1')
{
return $next($request);
}
else
{
return redirect('/home');
}
}
}
The code as is produces the following result:
- When an Officemanager logs in, he/she is redirected to the proper routes. Everything works fine.
- When an Employee logs in, he/she gets redirected to the /home redirect (bottom of routing/web.php file).
Any clues or help is very welcome. Kinda stuck on something probably basic.
[UPDATE]
In kernel.php both classes are mapped:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'officemanager' => \App\Http\Middleware\Officemanager::class,
'employee' => \App\Http\Middleware\Employee::class,
];
The only thing that I can think of is that the Rolid of employee is not 3 - so try to debug it.
In general, it is not recommended to rely on DB ids in your code, because they can change between environments. I would add a relation for the user model and check the rol name:
User model:
public function role()
{
return $this->belongsTo('App\Role', 'Rolid');
}
Employee middlaware
class Employee
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user()->role->name == 'employee')
{
return $next($request);
}
else
{
return redirect('/home');
}
}
}
Office manger middleware:
class Officemanager
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user()->role->name == 'officemanager')
{
return $next($request);
}
else
{
return redirect('/home');
}
}
}

Pass parameter to Laravel Middleware

How can I passed a parameter in my middleware? I'm always getting this error
Here are the structure of my middlware
<?php
namespace App\Http\Middleware;
use Closure;
class SubDomainAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $subdomain)
{
dd($subdomain); // Just trying to output the result here
return $next($request);
}
}
And on the Kernel.php under the $routeMiddleware I added this
'subdomain.access' => \App\Http\Middleware\SubDomainAccess::class,
Now on my web.php route file I added this
Route::group(['domain' => '{subdomain}.' . config('site.domain')], function () {
Route::get('/', ['as' => 'site.home', 'uses' => 'Site\Listing\ListingController#showListing'])->middleware('subdomain.access');
});
Also I tried this
Route::group(['domain' => '{subdomain}.' . config('site.domain')], function () {
Route::group(['middleware' => 'subdomain.access'], function () {
Route::get('/', ['as' => 'site.home', 'uses' => 'Site\Listing\ListingController#showListing']);
});
});
I tried this but nothings working. The only thing I haven't tried is placing the middleware in my controller constructor. But I don't wan't it that way as I think this is messy and it's more elegant if its within the route file.
Hope you can help me on this. Thanks
Ok so I managed to find a way to get the parameters without passing a third parameter on the middleware handle function thanks to this link
So what I did to retrieve the subdomain parameter is this
$request->route()->parameter('subdomain')
or if all parameter
$request->route()->parameters()
['middleware' => 'subdomain.access'] is wrong, try to use ['middleware' => 'subdomain:access'] with a : instead.
https://mattstauffer.co/blog/passing-parameters-to-middleware-in-laravel-5.1
Get URI from $request object and then return domain. No need to pass subdomain as params to middleware.
namespace App\Http\Middleware;
use Closure;
class SubDomainAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $subdomain)
{
$sudomain = $this->getSubDomain($_SERVER['HTTP_HOST']);
return $next($request);
}
/**
* Get Subdomain name
* #param $uri
* #return bool
*/
private function getSubDomain($uri)
{
if(!empty($uri))
{
$host = explode('.', $uri);
if(sizeof($host) > 2)
return $host[0];
}
return false;
}
}

Resources