I am running laravel version 5.4.26
my localhost project url is : middleware.dev. first time login in this url :
middleware.dev/login
,and login successfully completed. Then enter this url :
middleware.dev/admin
,then error message bellow
This page isn’t working
middleware.dev redirected you too many times. Try clearing your
cookies. ERR_TOO_MANY_REDIRECTS
Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* 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,
'role'=>\App\Http\Middleware\RoleMiddleware::class,
'IsAdmin'=>\App\Http\Middleware\IsAdmin::class,
];
}
IsAdmin.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user =Auth::user();
if ($user->isAdmin()){
return redirect()->intended('/admin');
}
return $next($request);
}
}
web.php
<?php
/*
|--------------------------------------------------------------------------
| 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!
|
*/
use Illuminate\Support\Facades\Auth;
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/admin/user/roles',['middleware'=>['role','auth','web'],function (){
return 'Middleware role';
}]);
Route::get('/admin', 'AdminController#index');
AdminController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminController extends Controller
{
//
public function __construct()
{
$this->middleware('IsAdmin');
}
public function index(){
return 'you are administretor becuse you ar sign in the page';
}
}
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role(){
return $this->belongsTo('App\Role');
}
public function isAdmin(){
if ($this->role['name'] =='administrator'){
return true;
}
return false;
}
}
Try this in IsAdmin middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Route;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user =Auth::user();
if ($user->isAdmin() && Route::currentRouteAction() != 'App\Http\Controllers\AdminController#index' ){
return redirect()->intended('/admin');
}
return $next($request);
}
}
This problem is most probably due to a loop in your redirection like you redirect to a route which redirects you back to the same route forming a loop.
The problem seems to be with your logic in IsAdmin middleware. The logic reads If the user is admin then redirect to /admin otherwise pass the request where it is headed which is again /admin route.
This is where the problem is. For instance, you hit middleware.dev/admin it will cross through IsAdminmiddleware and on confirming that user is admin will again redirect it to /adminroute which creates a loop.
Try this inside IsAdmin.php Class:
public function handle($request, Closure $next)
{
$user = Auth::user();
if(!$user->isAdmin()){
return redirect('/');
}
return $next($request);
}
Related
Lets say I have the following route to display a specific user in an API point, that is protected via some authentication middle:
Route::get('/v1/user/{user}', 'Api\V1\UserController#show')->middleware('can:show,user');
Assume my database is filled with just a handfull records. Then, going to the route without a credential:
/api/v1/user/1 will give me 403 UNAUTHORIZED
/api/v1/user/999999 will give me 404 NOT FOUND
In this setup, any visitor can find out how many users I have, by just poking around and trying some routes. Moreover, they can also find out the primary identifier (the id) of these users. This is something I would like to hide from a business perspective, but also from a security perspective.
An appoach that partially addresses this issue, is using UUID's. UUIDs are universally unique alpha-numeric identifiers that are 36 characters long, and Laravel supports the use of these on your models. This will hide the amount of records our have, and make it hard to find existing records. However, since it is still statistically possible to find records by just brute forcing, I feel this is not the correct answer to this problem.
So, how can I prevent a Laravel security leak where API returns not found when you are not authenticated?
// Path: app/Http/Controllers/Api/V1/UserController.php
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function show(User $user)
{
return $user;
}
}
// Path: app/User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
// Path: routes/api.php
<?php
Route::get('/v1/user/{user}', 'Api\V1\UserController#show')->middleware('can:show,user');
// Path: app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
// Path: app/Http/Middleware/Can.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
class Can
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $ability
* #param array|string $arguments
* #return mixed
*
* #throws \Illuminate\Auth\Access\AuthorizationException
*/
public function handle($request, Closure $next, $ability, ...$arguments)
{
if (Gate::denies($ability, $arguments)) {
throw new AuthorizationException(
'This action is unauthorized.', null, Response::deny()
);
}
return $next($request);
}
}
// Path: app/Http/Kernel.php
<?php
namespace App\Http;
use App\Http\Middleware\Can;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* 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,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => Can::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}
// Path: app/Http/Controllers/Api/V1/UserControllerTest.php
<?php
namespace Tests\Feature\Api\V1;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class UserControllerTest extends TestCase
{
use RefreshDatabase;
public function testShow()
{
$user = factory(User::class)->create();
$response = $this->getJson("/api/v1/user/{$user->id}");
$response->assertStatus(200);
}
public function testShowUnauthorized()
{
$user = factory(User::class)->create();
$response = $this->getJson("/api/v1/user/{$user->id}");
$response->assertStatus(403);
}
public function testShowUnauthorizedWithPolicy()
{
$user = factory(User::class)->create();
$response = $this->getJson("/api/v1/user/{$user->id}");
$response->assertStatus(403);
}
}
// Path: app/Policies/UserPolicy.php
<?php
namespace App\Policies;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view the model.
*
* #param \App\User $user
* #param \App\User $model
* #return mixed
*/
public function show(User $user, User $model)
{
return $user->id === $model->id;
}
}
You can follow GitHub's technique and return a 404 (Not found) instead of 403 (Unauthorized).
This way, attackers don't know if the resource actually exists or not.
To achieve this in Laravel, you may do it like this:
In app/Exceptions/Handler.php, create/edit the method called render() and check if the status code is 403. If so, throw a 404 instead.
public function render($request, Throwable $exception)
{
if ($exception->getStatusCode() === 403) {
abort(404);
}
return parent::render($request, $exception);
}
If you want to test it, just add this test route in routes/web.php:
Route::get('/test', function () {
return abort(403); // should return a 404
});
Resources:
Related topic's discussion
Method render documentation
you can use this package to generate a slug.
Then you can use the slug instead of the id.
https://github.com/spatie/laravel-sluggable
I am new to Laravel and its 5.6 version.
I setup a Auth login using few commands over there. All is good going. But when I uploaded to my own live server then when I run site.com/admin [that should be redirect to site.com/login for non login scene]. But I got a blank page. When I ran site.com.login then login page is working and I am in admin panel to work on.
My question is that why my site.com/admin page is blank. all other pages are working fine.
here is my files.
routes/web.php
Route::get('/', 'HomeController#index')->name('home');;
Route::get('view/{slug?}', 'HomeController#view');
Auth::routes();
Route::prefix('admin')->group(function () {
Route::get('/', 'Admin\AdminController#admin_index')->name('admin_index');
Route::get('/dashboard', 'Admin\AdminController#dashboard')->name('dashboard');
Route::get('locations', 'Admin\LocationsController#locations')->name('locations');
Route::get('add-location', 'Admin\LocationsController#add_location')->name('add-location');
Route::post('submit-location', 'Admin\LocationsController#submit_location')->name('submit-location');
Route::get('posts', 'Admin\PostsController#posts')->name('posts');
Route::get('add-post', 'Admin\PostsController#add_post')->name('add-post');
Route::post('submit-post', 'Admin\PostsController#submit_post')->name('submit-post');
});
Route::get('/clear-cache', function() {
$exitCode = Artisan::call('cache:clear');
});
Route::get('/logout', '\App\Http\Controllers\Auth\LoginController#logout')->name('logout');
app/Http/Kernel.php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* 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,
'is_admin' => \App\Http\Middleware\IsAdmin::class,
];
}
app/Http/isAdmin.php
namespace App\Http\Middleware;
use Closure;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// return $next($request);
if(auth()->user()->isAdmin()) {
return $next($request);
}
return redirect('login');
//return $next($request);
}
}
AdminController.php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class AdminController extends Controller {
public function __construct(){
$this->middleware('auth');
}
public function admin_index() {
return view('admin.index');
}
public function dashboard() {
return view('admin.dashboard');
}
public function admin() {
return view('admin.index');
}
}
anything else I can share please let me know.
Change:
Route::prefix('admin')->group(function () {
Route::get('/', 'Admin\AdminController#admin_index')->name('admin_index');
Route::get('/dashboard', 'Admin\AdminController#dashboard')->name('dashboard');
Route::get('locations', 'Admin\LocationsController#locations')->name('locations');
Route::get('add-location', 'Admin\LocationsController#add_location')->name('add-location');
Route::post('submit-location', 'Admin\LocationsController#submit_location')->name('submit-location');
Route::get('posts', 'Admin\PostsController#posts')->name('posts');
Route::get('add-post', 'Admin\PostsController#add_post')->name('add-post');
Route::post('submit-post', 'Admin\PostsController#submit_post')->name('submit-post');
});
To:
Route::group([
'middleware' => ['auth', 'is_admin'],
'namespace' => 'Admin',
'prefix' => 'admin',
], function () {
Route::get('/', 'AdminController#admin_index')->name('admin_index');
Route::get('/dashboard', 'AdminController#dashboard')->name('dashboard');
Route::get('locations', 'LocationsController#locations')->name('locations');
Route::get('add-location', 'LocationsController#add_location')->name('add-location');
Route::post('submit-location', 'LocationsController#submit_location')->name('submit-location');
Route::get('posts', 'PostsController#posts')->name('posts');
Route::get('add-post', 'PostsController#add_post')->name('add-post');
Route::post('submit-post', 'PostsController#submit_post')->name('submit-post');
});
And:
if(auth()->user()->isAdmin()) {
To:
if(optional(auth()->user())->isAdmin()) {
Be sure you have isAdmin() function in your User model which return true or false
Your issue is that you are not using isAdmin middleware.
You can use middleware on route to check the admin role.
I have middleware called IsAdmin, here is the code for it:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Auth::user();
if ($user->role === 10)
{
Session::flash('error', 'Трябва да сте администратор за да видите тази страница.');
return redirect('/home');
}
return $next($request);
}
}
here is registering it in the kernel:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* 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,
'isadmin' => \App\Http\Middleware\IsAdmin::class,
];
}
and here is how I am protecting the routes in the controllers:
public function __construct()
{
$this->middleware(['auth', 'isadmin']);
}
the auth middleware works just fine.
The isadmin middleware stopped working when I changed the permission field I use in the database, on the user model. It used to be "$user->is_admin" and I've changed it to "$user->role" now even reverting back to the old way doesn't fix the problem.
Here is also the migration for the User model:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->tinyInteger('role')->default(0);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Here are also my routes or web.php file:
<?php
/*
|--------------------------------------------------------------------------
| 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('auth.login');
});
Auth::routes();
Route::get('/home', 'ReportController#home')->name('home');
Route::get('/dashboard', 'HomeController#dashboard')->name('dashboard');
Route::resource('/obekti', 'ObektiController');
Route::resource('/entrances', 'EntrancesController');
Route::resource('/apartments', 'ApartmentsController');
Route::resource('/people', 'PeopleController');
Route::resource('/boardmembers', 'BoardMembersController');
Route::resource('/companies', 'CompaniesController');
Route::get('/apartments/{id}/people', 'ApartmentsController#people');
Route::get('/entrances/{id}/apartments', 'EntrancesController#apartments');
Route::get('/obekti/{id}/entrances', 'ObektiController#entrances');
Route::get('/obekti/{id}/boardmembers', 'ObektiController#boardMembers');
Route::post('/search', 'HomeController#search');
If you are including your middleware inside $routeMiddleware property then you can use the middleware method to assign middleware to a route:
try this
Route::get('/dashboard', 'HomeController#dashboard')->name('dashboard')->middleware(['isadmin','auth']);
or you can use the group method
Route::group(['middleware' => ['isadmin', 'auth']], function () {
//
});
The problem was this line:
if ($user->role === 10)
it should've been this:
if ($user->role === 0)
I decided to dig into middleware, because I need to check on every request if the user is a pre-user (just a user that hasn't changed password yet), except for the change-password route. My code for the middleware is following:
<?php
namespace App\Http\Middleware;
use Closure;
class IsPreuser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (\Auth::user()->is_preuser)
{
if (\Route::getCurrentRoute()->getName() == 'profile.change_password')
{
echo 'hello';
}
//return redirect()->route('profile.change_password');
}
return $next($request);
}
}
My route name is profile.change_password. With the above code I am getting the error Call to a member function getName() on null I don't understand. My goals are: to redirect to the profile.change_password route except when the user already is in this route.
My kernel.php:
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\IsPreuser::class
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
//Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* 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,
];
}
Okay, fixed it. As suggested in the comments, the problem could be the placement of my middleware. I moved it to $middlewareGroups in web and it works as expected, with the redirect.
<?php
namespace App\Http\Middleware;
use Closure;
class IsPreuser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (\Auth::check())
{
if (\Auth::user()->is_preuser)
{
if (! $request->routeIs('profile.change_password')
&& ! $request->routeIs('profile.change_password_process')
&& ! $request->routeIs('logout'))
{
return redirect()->route('profile.change_password');
}
}
}
return $next($request);
}
}
I want to guest users have access to home page but in built in authentication process laravel redirects to login page. how can i give guest users access to home page?
my routes.php:
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', 'HomeController#index');
Route::get('/insert', 'HomeController#insertform');
Route::get('/job/{id}', 'JobsController#show');
Route::get('/city/{city}', 'JobsController#city');
Route::post('/insert', 'HomeController#insert');
Route::get('/cityinsert', 'HomeController#cityinsert');
Route::post('/cityinsert', 'HomeController#cityinsertpost');
});
and authenticate.php
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
}
and this is my kernel.php
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
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,
],
'api' => [
'throttle:60,1',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
}
I prefer to exclude middleware via routes. You can do it in two ways:
Single action:
Route::post('login', 'LoginController#login')->withoutMiddleware(['auth']);
Group mode:
Route::group([
'prefix' => 'forgot-password',
'excluded_middleware' => ['auth'],
], function () {
Route::post('send-email', 'ForgotPasswordController#sendEmail');
Route::post('save-new-password', 'ForgotPasswordController#saveNewPassword');
});
Tested on Laravel 7.7
Add an exception in the middleware declaration in the construct
Route::get('/', 'HomeController#index');
for the above route to be exempted from authentication you should pass the function name to the middleware like below
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth', ['except' => 'index']);
}
}
Remove the middleware from HomeController construct:
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
//$this->middleware('auth');
}
}
I can add to Sidharth answer, that you can use several methods exeption, by including them in array:
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth', ['except' => ['index', 'show']]);
}
}
Laravel 5.5 tested.
You can also separate between middleware and except. Try this one :
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except([
'submitLogout',
'showUserDetail'
]);
}
Tested on Laravel 5.4
Add except URL to VerifyCsrfToken
app/http/middleware/VerifyCsrfToken.php
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
];
}
Source: Laravel Documentation CSRF exclude URL
*Tested on Lavarel 7.0 as well
Recently I need that functionality in an old Laravel project.
God bless Laravel for macroable feature :)
AppServiceProvider.php
public function boot()
{
Route::macro('withoutMiddleware', function ($excludedMiddlewares) {
$this->action['middleware'] = array_filter(
$this->action['middleware'],
function ($middleware) use ($excludedMiddlewares) {
return !in_array($middleware, $excludedMiddlewares);
});
return $this;
});
}
Then you can use it like this:
Route::get('something')->withoutMiddleware(['auth']);