Laravel newbie here (obviously :D ). I've set up a new model & controller for a model named Pages.
Every User has many Pages.
Each Page has a single User.
I've created the following functioning controller actions (& views):
PagesController::index
PagesController::create
PagesController::store
PagesController::show
PagesController::edit
PagesController::delete
So you can edit a Page by going to url.dev/pages/{id}/edit.
The problem is, you can access all of these routes regardless of your session status. So random users can edit any given Page. Which, obviously, is terrible.
Can anyone point me in the direction of what I should read up on, to limit the ability to access my model's controller actions based on whether or not the user is logged in (and if it's the correct user, at all)?
To force a specific route to be only accessible by authenticated users you can specify middleware auth in the controller constructor, like so:
public function __construct()
{
$this->middleware('auth');
}
Also you can restrict which methods you want auth to be applied to in the controller, using the only or except parameters. Using only you could do:
public function __construct()
{
$this->middleware('auth', ['only' => ['create', 'store', 'edit', 'delete']]);
}
You´re looking for middleware..
You can read more here
public function __construct()
{
$this->middleware('auth')->only('index');
$this->middleware('admin')->except('store');
}
Other answers are good, but I prefer to use middleware on route groups.
So when I have several routes like this:
Route::get('pages', 'PagesController#index')->name('pages.index');
Route::get('pages/{id}/edit', 'PagesController#edit')->name('pages.edit');
I would add them inside Laravel Route group. Like this:
Route::group(['middleware' => 'auth'], function() {
Route::get('pages', 'PagesController#index')->name('pages.index');
Route::get('pages/{id}/edit', 'PagesController#edit')->name('pages.edit');
});
Related
so i have my routes defined within a global route group and inside i have two others groups, on with middleware 'employee' and one with middleware 'admin' and each one have their own controllers.
The two groups have a route index with the same url " /document " but each executes a different controller.
My problem is the index route that the last defined group always overrides the previous one.
The wanted behaviour is that if employee middleware is valid, execute the empController#index action, else if the admin controller is valid, execute the adminController#index action while keeping the same url for both, and i must keep each route in a seperate group, and the two routes must have the same url.
How can i acheive that? Thanks
here are the two conflicting routes
Route::group(['as' => 'admin.', 'middleware' => ['admin']], function() { Route::get('/document', 'Admin\DocumentController#index')->name('document.index'); .... });
Route::group(['middleware' => ['employee']], function() { Route::get('/document', 'DocumentController#index')->name('document.index'); .... });
It sounds like you want to perform different actions based on whether the request is coming from an employee or an admin. My suggestion would be to have one url, one route and one controller function for this.
Within the controller function (or in middleware that attaches its findings to the request if you wanted to do that), have logic to call one method or another.
A pseudo example in PersonController.php:
if(\Auth::user()->isAdmin()) {
// return an admin view or perform an admin function
else {
// return an employee view or perform an employee function
}
Where the isAdmin() function is something you've defined in a model like User.php.
I use Laravel 5.3 and I have the following problem.
[UPDATE]
My initial trouble was the appearance of an error when performing actions on the site when the user was not logged in the system.
This happened when the browser is started, where cached information is displayed by default on the page. Site interface displayed for logged users, and in his system was not. At the same time, producing some action, I get an error that the user is not authorized.
I also have group auth middleware for all my routes. When I reboot page of the site, the middleware is activated and redirectedme to the login page. The main problem is the browser shows the cached information.
So, in addition to middleware for routes I decided to make auth check in controllers.
[/UPDATE]
I want to check user's auth in every controller's action. Making the auth check in every controllers' action manually isn't a solution, because there are many controllers and actions.
So I decided to make it globally.
As all controllers extends Main Controller (App\Http\Controllers\Controller.php), I decided write the
auth()->check() in constructor:
function __construct()
{
if(auth()->check()) dd('success');
}
But... nothing happened((( Then I found the callAction method in BaseController which Main Controller extends and made checking here:
public function callAction($method, $parameters)
{
if(auth()->check()) dd('success');
return call_user_func_array([$this, $method], $parameters);
}
This time everything's OK, but I don't like this solution, because editing the core files isn't good.
Finally, I redeclared callAction method in Main Controller with auth checking, but I don't like this way too.
Is any solution?
You should use middleware:
Route::get('profile', ['middleware' => 'auth', 'uses' => 'UserController#showProfile']);
Or:
Route::get('profile', 'UserController#show')->middleware('auth');
Or using middleware groups:
Route::group(['middleware' => ['auth']], function () {
// Controllers here.
});
Or using controller's construct:
public function __construct()
{
$this->middleware('auth');
}
You can use auth middleware in your controller
public function __construct()
{
$this->middleware('auth');
}
check here : https://laravel.com/docs/5.3/authentication
if there is a group of routes this would be the easiest way
Route::group(['middleware' => ['auth']], function()
{
// here all of the routes that requires auth to be checked like this
Route::resource('user','UsersController');
}
another ways
function __construct()
{
$this->middleware('auth');
}
another way is specified on controller routes
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController#showProfile'
]);
see documentation
https://laravel.com/docs/5.0/controllers#controller-middleware
I have a middleware that detects if a user owns a tournament.
So, if user want to edit a tournament he doesn't own, he will get a 403.
Thing is I can't make difference between laravel.dev/tournament/1/edit, and laravel.devl/tournament/1
Off course, I could check the "edit" word in URL, but I would prefer other better param...
I tried method param in Request Object, but it is giving me GET for both, so I can't make difference...
Any Idea???
In your case, you can do like this:
$request->route()->getName();
Now you can do your logic based on this.
What about using a different HTTP method for edit, e.g PATCH or PUT and declaring two different routes, something like:
Route::get('laravel.devl/tournament/1', 'TournamentController#showTournament');
Route::put('laravel.dev/tournament/1/edit', 'TournamentController#editTournament');
Then in the TournamentController you can check if the user has rights to edit.
It sounds like you should just use route specific middleware instead of global middleware. See https://laravel.com/docs/master/middleware#assigning-middleware-to-routes. Then you can just do:
Route::get('/tournament/{id}/edit', ['middleware' => ['tournamentOwner'], function () {
//
}]);
Route::get('/tournament/{id}', ['middleware' => [], function () {
//
}]);
If it's a RESTful route, you can just do:
public function __construct()
{
$this->middleware('tournamentOwner', ['only' => ['edit']]);
}
I am using Laravel 5.1 for my project. I am trying to secure Routes and make sure only logged in user can access certain routes. I am aware about middlewares but I am wondering if anyone post an example or a link explaining about middleware and how to protect a page using middleware.
Thanks
To build on the answer given by Joe Rose, you can also specify the middleware in your controller rather than in your routes.php file.
E.g you could have your routes set out like
Route::get('/example', 'ExampleController#index');
Route::post('/example/post', 'ExampleController#post');
Route::resource('blog', 'BlogController');
And then inside your controller reference it like so:
class ExampleController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
//....
If you're looking for more info, check out the link to the docs Joe gave, and also this blog post which explains what middleware is really well and how to create your own if you need to.
You are correct about using middleware. The included Auth middleware is what you should use, as long as you are also using the included Auth controller to authenticate users. You would write your route like this:
Route::get('/page', array(
'uses' => 'Controller#method',
'middleware'=>'auth'
));
(The above example is using a GET request, but it could other request types, like POST for example).
This will use the default behavior of the middleware which checks to see if the user is logged in (authenticated). You can also extend or overwrite the built-in functions to allow you to direct the application on where to send the user if they are or are not logged in, etc. Laravel's official documentation is a good starting point: link
I have this blog resource which has the usual CRUD methods.(index, create, store, show, edit, update, destroy).
I have the following route in my routes.php:
Route::resource('blog', 'PostsController');
but I want to restrict all but index and show.
so I have
Route::get('blog', 'PostsController#index');
Route::group(array('before' => 'auth'), function()
{
Route::resource('blog', 'PostsController');
});
which is fine for index but I don't know how to route the show method ? Or is there another way? Instead of routing the resource should I route every URI individually and put the ones I want restricted in my restricted access route?
Cheers
Laravel has a feature that lets you specify filters in the controllers' __construct method using $this->beforeFilter. This function takes a second argument that lets your provide exceptions (or enable the filter only for certain methods). Try using your original routes file and set up your controller like this:
class PostsController extends BaseController {
function __construct() {
// ...
$this->beforeFilter('auth', array('except' => array('index', 'show')));
// ...
}
// ...
See Controller Filters in the Laravel documentation. It's not entirely well-documented, but you can also start a deeper journey into the guts of Laravel from here.
In Laravel 5 you use middleware function instead like this:
$this->middleware('auth', array('except' => array('index', 'show')));