So I have my auth middleware, which is registered in the Http/Kernel.php as:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];
Next I made a change to the middleware handle function in the Authenticate class:
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
$user = $this->auth->user();
$currentDateTime = strtotime('Y-m-d H:i:s');
$tokenExpirationTile = strtotime($user->token_expiration);
if ($currentDateTime <= $tokenExpirationTile) {
return $next($request);
} else {
$this->auth->logout();
redirect('home/login')->with('message', 'Your session has expired. Please login in again');
}
} else {
redirect('home/login')->with('message', 'Please login before attempting to access that');
}
}
And finally I created the route:
Route::get('home/dashboard', 'HomeController#dashboard', ['middleware' => 'auth']);
I can visit this route but as a non signed in user I should be redirected.
When I through a dd() in the handle function nothing happens.
How do I get it to run this method on this route?
Also when it comes to other controllers where you need to authenticate before each action request how do you say: "before each action, run this method." In rails I would do before_action :method_name
For the second part of your question, please consult the docs for how to apply middleware to specific actions in a controller and on routes:
http://laravel.com/docs/master/controllers#controller-middleware
http://laravel.com/docs/master/routing#route-group-middleware
For the first part, have you tried running 'composer dump-autoload' from the terminal?
Related
I have been working on a multi-tenant app and I'm trying to set up the routes in sub-domains according to the documentation:https://laravel.com/docs/5.7/routing#route-group-sub-domain-routing
In my web.php route file, I have something like this:
Route::domain('{account}.example.test')->group(function () {
Route::get('/home', 'HomeController#index')->name('home');
});
Right now, the problem is using named routes in blade, but I suppose I may run into the same problem eventually in my Controllers.
Whenever I try to used a named route like this:
Blade Code
Home
I get the following error:
Missing required parameters for [Route: home] [URI: home]. (View: /home/vagrant/Code/example/resources/views/example.blade.php)
I have found a way for solving this, you just have to:
Home
I also "solved" this using a helper...
if (! function_exists('acctRoute')) {
function acctRoute($name = '')
{
return route( $name, request('account'));
}
}
So I can use it like:
Home
But I'm still wondering if there's a cleaner way to do this, maybe with some middleware that always injects the parameter?
This is my answer to my own question in case anyone needs this in the future:
From here I noticed that you can set default values for all routes under a middleware:
https://laravel.com/docs/5.7/urls#default-values
So... This is what I ended up doing
First create the middleware:
php artisan make:middleware MyMiddleware
Then update the handle method inside the created middleware as in the documentation example:
public function handle($request, Closure $next)
{
URL::defaults(['account' => request('account')]);
return $next($request);
}
Then register the Middleware in Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::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,
'mymiddle' => \App\Http\Middleware\MyMiddleware::class,
];
Then use it as any other middleware in your routes files:
Route::domain('{account}.example.test')->middleware('mymiddle')->group(function () {
Route::get('/home', 'HomeController#index')->name('home');
});
And finally, use the route helper function as usual:
Home
You could share the account (subdomain) variable across all views:
// AppServiceProvider
public function boot()
{
View::share('subdomain', request('account'));
}
// blade
Home
Another approach could use a service container binding:
// AppServiceProvider
$this->app->bind('account.route', function () {
return route('home', request('route'));
});
// blade
Home
This is my route:
Route::group(['middleware' => ['web']], function () {
Route::get('/xx', 'xx\yy#zz');
This is my modification in Kernel.php:
protected $middlewareGroups = [
'web' => [
\Keevitaja\Linguist\LocalizeUrls::class,
LocalizeUrls.php:
public function handle($request, Closure $next)
{
if ($this->linguist->hasDefaultSlug() && $this->linguist->isDefaultDenied()) {
abort(404);
}
if (Sentinel::check())
{
dd("logged in");
}
dd("NOT logged in");
I am using Sentinel and Linguist for authentication and localisation.
I would like to get 'system_language' from the User model: check if the user is logged in and if he is, I would like to get his preferred language from the DB and then pass it to Linguist:
$this->linguist->localize('fr');
Unfortunately, Sentinel:check() always returns FALSE in this middleware. In my own middleware it is working well.
For sure, I am using the right Facade of Sentinel, because $sentinel = Sentinel::findById(1); returns a valid result.
The problem was caused because of the order in the Kernel.php $middlewareGroups where \Keevitaja\Linguist\LocalizeUrls::class was on first position.
This question already has an answer here:
Login laravel Trying to get property of non-object
(1 answer)
Closed 3 years ago.
I recently change my authentication to Sentinel and everything seems to work beside the following problem: when the user is not authenticated, I would like to redirect him to the login page, but I always get an error "Trying to get property of non-object"
I have commented several standard middleware from the Kernel.php:
protected $middlewareGroups = [
'web' => [
// \Illuminate\Session\Middleware\AuthenticateSession::class,
protected $routeMiddleware = [
// 'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
// 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
// 'can' => \Illuminate\Auth\Middleware\Authorize::class,
// 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
And I have added a new middleware by myself:
<?php
namespace App\Http\Middleware;
use Closure;
use Sentinel;
class AdminMiddleware
{
public function handle($request, Closure $next)
{
if (Sentinel::check())
{
if (Sentinel::getUser()->roles()->first()->slug == 'admin' ||
Sentinel::getUser()->roles()->first()->slug == 'superuser' )
{
return $next($request);
}
}
else
{
return redirect('/login')
->with(['error' => "You do not have the permission to enter this site. Please login with correct user."]);
}
}
}
In case the user is logged in and I return the request, everything is working well. In case the user is not logged in or have a too low level, there will be an error triggered when the redirect is executed:
"Trying to get property of non-object"
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php
$response->headers->setCookie(
Don't use an else in there! Otherwise, the case that Sentinel::check() is true but the user has not the right slugs isn't covered by any return value at all!.
public function handle($request, Closure $next)
{
if (Sentinel::check())
{
if (Sentinel::getUser()->roles()->first()->slug == 'admin' ||
Sentinel::getUser()->roles()->first()->slug == 'superuser' )
{
return $next($request);
}
}
return redirect('/login')
->with(['error' => "You do not have the permission to enter this site. Please login with correct user."]);
}
}
This is my first attempt at a laravel package and have run into an issue where Auth::attempt($credentials) works within my login controller, but upon redirection to a protected route or controller, the user is no longer authenticated. Below is my login controller method with the redirect to dashboard commented out.
public function attempt(Request $request){
$email = strtolower(strip_tags(htmlspecialchars($request->input('email'))));
$password = strip_tags(htmlspecialchars($request->input('password')));
if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
// Redirect to dashboard route
//return redirect()->intended('/admin');
if(Auth::check())
print_r(Auth::user());
}
}
A response to valid credentials prints out the correct user record and Auth::check returns true. But, when redirected to the admin controller, the user is not authenticated. Below is the admin controller method that should output the authenticated user, but only returns "not logged".
public function index()
{
if(Auth::check()) print_r(Auth::user());
else echo "not logged";
}
Both controllers use Auth;, their namespaces are consistent with vendor/package/pathToDir, db is setup correctly, and the encryption key has been set. Any ideas on what's going wrong? Thanks
Turns out the issue was with the new web middleware, moved all my routes that require session data in to the route group and everything works as normal.
Route::group(['middleware' => ['web']], function () {
Route::get("/login", ['uses'=>'SiteLogin#index']);
Route::post("/login", ['uses'=>'SiteLogin#attempt']);
Route::get("/logout", ['uses'=>'SiteLogin#logout']);
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function () {
Route::get('/', ['uses'=>'Admin#index']);
});
});
The default behavior of the method attempt is to not keep the user logged.
You should change it to:
if (Auth::attempt(array('email' => $email, 'password' => $password), false, true))
This way you will set remember as false and login as true.
Check more about this here: https://laravel.com/docs/5.2/authentication
I am new to Laravel but fell in love with the framework and decided to use it for my project.
I have a field active and by default I've set it to 0. In the Attempt() method, I've set $credentials['active'] = 1. When I logout and login again, this works fine.
But when I register a user, it automatically logs the user in without checking active field.
I assume you are using the AuthenticatesAndRegistersUsers trait in your controller.
The registration is carried by the postRegister() method in that trait, which calls the login() method after creating a new user.
You can override this method in your controller and call the login() method only when the active field is true. So, your postRegister() method will be something like:
public function postRegister(Request $request)
{
$validator = $this->registrar->validator($request->all());
if ($validator->fails())
{
$this->throwValidationException(
$request, $validator
);
}
$user = $this->registrar->create($request->all());
if ($request->get('active')) {
$this->auth->login($user);
}
return redirect($this->redirectPath());
}
In registersUsers.php replace the line:
Auth::guard($this->getGuard())->login($this->create($request->all()));
With the following:
$this->create($request->all());
This worked for me, I use Laravel 5.2
I would avoid adding the active field to the credentials - this is an authorisation issue rather than an authentication one.
For this, I'd use a middleware to check if a logged-in user is active or inactive.
In 5.3, the middleware would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfInactive
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ( $user = Auth::guard('web')->user() ) {
if ( ! $user->active )
return redirect(route('account_inactive'));
}
return $next($request);
}
}
This middleware then has to be registered inside Kernel.php:
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,
'inactive' => \App\Http\Middleware\RedirectIfInactive::class,
];
And then finally we protect all our routes with it:
Route::get('inactive', ['as' => 'account_inactive', function () {
return view('inactive');
}]);
Route::group(['prefix' => 'admin', 'namespace' => 'Admin', 'middleware' => 'inactive'], function () {
Route::get('/', ['as' => 'admin.home', 'uses' => 'AdminController#index']);
});
The advantage of this approach of course is that we can display a more relevant error message than the general 'These credentials do not match our records' that people with bad auth details get. So the user would know it's not their fault they can't log in.
Anyway, with the approach in the accepted answer, ensure you have done the same for when the user successfully resets their password as they are also auto-logged in then.
For future reference, you could just override the registered method and inside it, destroy all sessions by using Auth::logout. The user will by default be redirected to Login page