laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.51k stars 11.02k forks source link

Middleware defined before a route runs even when not asked #22156

Closed pbarnum closed 6 years ago

pbarnum commented 6 years ago

Description:

The middleware seems to have a "trickle-down" effect, causing undesired results to the routes. In my web routes file, I have defined user routes with the auth middleware. Below the user routes, I defined the blog routes, which do not use the auth middleware. When I try to access the blog route, I am redirected to the login page because I am not authorized to view what has been requested.

Steps To Reproduce:

Define a route and attach a middleware to it. Define another route below the first without the middleware attached. When attempting to access the second route, the middleware should still run even when you didn't specify the route to use it.

If this is intended behavior, perhaps the documentation could be updated to reflect it. And if it is, please provide a link, I wasn't able to find it.

davidcb commented 6 years ago

I have tested this and didn't get that behaviour.

Route::get('test', ['middleware' => 'auth'], function() { echo 'must login'; }); Route::get('test2', function() { echo 'it works'; });

If I go to /test it redirects me to login page and if I go to /test2 it prints "it works".

Are you sure you don't have your blog routes inside a group with the auth middleware or that middleware directly in your controller?

Dylan-DPC-zz commented 6 years ago

Can you share some code please?

Kyslik commented 6 years ago

@pbarnum what does your $ php artisan route:list say?

pbarnum commented 6 years ago

php artisan route:list

$ php artisan route:list
+--------+----------+-------------------------+--------------------+------------------------------------------------------------------------+--------------+
| Domain | Method   | URI                     | Name               | Action                                                                 | Middleware   |
+--------+----------+-------------------------+--------------------+------------------------------------------------------------------------+--------------+
|        | GET|HEAD | /                       |                    | App\Http\Controllers\PublicController@index                            | web          |
|        | PUT      | admin/add               | addBlog            | App\Http\Controllers\BlogController@addBlog                            | web,isAdmin  |
|        | GET|HEAD | admin/dashboard         | adminDashboard     | App\Http\Controllers\AdminController@dashboard                         | web,isAdmin  |
|        | POST     | admin/role/{id}/status  | toggleRoleStatus   | App\Http\Controllers\AdminController@toggleRoleStatus                  | web,isAdmin  |
|        | POST     | admin/roles             | rolePut            | App\Http\Controllers\AdminController@putRole                           | web,isAdmin  |
|        | GET|HEAD | admin/roles             | roles              | App\Http\Controllers\AdminController@roles                             | web,isAdmin  |
|        | GET|HEAD | api/user                |                    | Closure                                                                | api,auth:api |
|        | GET|HEAD | blog                    | blogs              | App\Http\Controllers\BlogController@index                              | web          |
|        | GET|HEAD | blog/{id}               | viewBlog           | App\Http\Controllers\BlogController@viewBlog                           | web          |
|        | DELETE   | blog/{id}/delete        | deleteBlog         | App\Http\Controllers\BlogController@deleteBlog                         | web,isAdmin  |
|        | GET|HEAD | blog/{id}/edit          | editBlog           | App\Http\Controllers\BlogController@editBlog                           | web,isAdmin  |
|        | POST     | blog/{id}/update        | updateBlog         | App\Http\Controllers\BlogController@updateBlog                         | web,isAdmin  |
|        | POST     | login                   | loginPost          | App\Http\Controllers\Auth\LoginController@login                        | web,guest    |
|        | GET|HEAD | login                   | login              | App\Http\Controllers\Auth\LoginController@showLoginForm                | web,guest    |
|        | GET|HEAD | logout                  | logout             | App\Http\Controllers\Auth\LoginController@logout                       | web          |
|        | POST     | password/email          | forgotPasswordPost | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail  | web,guest    |
|        | POST     | password/reset          | resetPasswordPost  | App\Http\Controllers\Auth\ResetPasswordController@reset                | web,guest    |
|        | GET|HEAD | password/reset          | forgotPassword     | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest    |
|        | GET|HEAD | password/reset/{token}  | resetPassword      | App\Http\Controllers\Auth\ResetPasswordController@showResetForm        | web,guest    |
|        | GET|HEAD | register                | register           | App\Http\Controllers\Auth\RegisterController@showRegistrationForm      | web,guest    |
|        | POST     | register                | registerPost       | App\Http\Controllers\Auth\RegisterController@register                  | web,guest    |
|        | GET|HEAD | store                   | store              | App\Http\Controllers\StoreController@index                             | web,auth     |
|        | GET|HEAD | store/product           | storeProduct       | App\Http\Controllers\StoreController@product                           | web,auth     |
|        | GET|HEAD | {user}                  |                    | App\Http\Controllers\UserController@dashboard                          | web          |
|        | GET|HEAD | {user}/dashboard        | userDashboard      | App\Http\Controllers\UserController@dashboard                          | web          |
|        | GET|HEAD | {user}/profile          | userProfile        | App\Http\Controllers\UserController@profile                            | web          |
|        | POST     | {user}/profile/identity | userIdentityPost   | App\Http\Controllers\UserController@updateIdentity                     | web          |
|        | POST     | {user}/profile/personal | userPersonalPost   | App\Http\Controllers\UserController@updatePersonal                     | web          |
|        | GET|HEAD | {user}/settings         | userSettings       | App\Http\Controllers\UserController@settings                           | web          |
|        | GET|HEAD | {user}/wishlist         | userWishlist       | App\Http\Controllers\UserController@wishlist                           | web          |
+--------+----------+-------------------------+--------------------+------------------------------------------------------------------------+--------------+

routes/web.php

// Public access pages
Route::get('/', 'PublicController@index');

// Registration Routes...
Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
Route::post('register', 'Auth\RegisterController@register')->name('registerPost');

// Authentication
Route::get('/login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('/login', 'Auth\LoginController@login')->name('loginPost');
Route::get('/logout', 'Auth\LoginController@logout')->name('logout');

// Password Reset Routes...
Route::get('/password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('forgotPassword');
Route::post('/password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('forgotPasswordPost');
Route::get('/password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('resetPassword');
Route::post('/password/reset', 'Auth\ResetPasswordController@reset')->name('resetPasswordPost');

// User routes
Route::prefix('/{user}')->group(function ($userRoutes) {
    $userRoutes->get('/', 'UserController@dashboard');
    $userRoutes->get('/dashboard', 'UserController@dashboard')->name('userDashboard');
    $userRoutes->get('/profile', 'UserController@profile')->name('userProfile');
    $userRoutes->get('/settings', 'UserController@settings')->name('userSettings');
    $userRoutes->get('/wishlist', 'UserController@wishlist')->name('userWishlist');

    $userRoutes->post('/profile/identity', 'UserController@updateIdentity')->name('userIdentityPost');
    $userRoutes->post('/profile/personal', 'UserController@updatePersonal')->name('userPersonalPost');
});

// Blog routes
Route::prefix('/blog')->group(function ($blogRoutes) {
    $blogRoutes->get('/', 'BlogController@index')->name('blogs');
    $blogRoutes->get('/{id}', 'BlogController@viewBlog')->name('viewBlog');
});

// Store routes
Route::prefix('/store')->middleware('auth')->group(function ($storeRoutes) {
    $storeRoutes->get('/', 'StoreController@index')->name('store');
    $storeRoutes->get('/product', 'StoreController@product')->name('storeProduct');
});

// Admin routes
Route::prefix('/admin')->middleware('isAdmin')->group(function ($adminRoutes) {
    $adminRoutes->get('/dashboard', 'AdminController@dashboard')->name('adminDashboard');

    $adminRoutes->put('/add', 'BlogController@addBlog')->name('addBlog');
    $adminRoutes->get('/{id}/edit', 'BlogController@editBlog')->name('editBlog');
    $adminRoutes->post('/{id}/update', 'BlogController@updateBlog')->name('updateBlog');
    $adminRoutes->delete('/{id}/delete', 'BlogController@deleteBlog')->name('deleteBlog');

    $adminRoutes->get('/roles', /*RoleController*/'AdminController@roles')->name('roles');
    $adminRoutes->post('/roles', /*RoleController*/'AdminController@putRole')->name('rolePut');
    $adminRoutes->post('/role/{id}/status', /*RoleController*/'AdminController@toggleRoleStatus')
        ->name('toggleRoleStatus');
});

The UserController.php class had $this->middleware('auth'); in its constructor, instead of defined within the route file. Removing this code sent me a 404 error when requesting the blog page. The only thing that fixed the issue was moving the blog route group above the user route group.

Dylan-DPC-zz commented 6 years ago

you shouldn't use a wildcard as a prefix to a route. That way any route after it, will still match the wildcard.

pbarnum commented 6 years ago

You're speaking in reference to the /{user} prefix? Interesting, that explains the 404 I received when I removed the auth middleware from the UserController. Well, if this issue doesn't result in a code or documentation change, then hopefully it will save the next developer days of confusion.

Thanks for the explanation!

themsaid commented 6 years ago

Please ask on the forums, this repo is for bug reporting only. You can use https://laracasts.com/discuss or https://laravel.io/forum which are forums with a very large community of developers helping each other.