I'm working on a laravel 5.1 application and I want to check if a user session has expired after each request, in order to redirect the user to the login page.
in order to do so I have created a middleware that runs on every request, the handle function looks like this
public function handle($request, Closure $next)
{
if(session_status() === PHP_SESSION_NONE)
{
return redirect()->guest('login');
}
return $next($request);
}
this does not seem to work correctly, because when I type 'localhost:8000' in google chrome it says 'localhost redirected you too many times', I guess it is because the session have not been started since the user is not logged in, so... is there any better way to do this checking?
You can disable middleware in certain routes. by adding the login route to the excepted_urls array. For example, add the following at the beginning of the class:
protected $except_urls = [
'login'
];
or you can disable it in your web.php/routes.php depending of the version of Laravel you're using by employing route grouping
Related
I want to know if there is a proper method of going about say I am a admin on my site and a user is browsing in the site already logged in and I go in and set their account status to 2 (In Active)
1 = Active
2 = In Active
3 = Terminated
Laravel doesn't automatically check so I would need to create, I am guessing middleware, but I am unsure on how to go about writing the code for my 2 different guards (admin and web). With my login function I use laravel's documentation for checking if status is equal to 1 so I already don't have to worry about them logging in again but if their session is already started I need to end it and I am guessing run a middleware on every HTTP request check and see if both or just 1 guard is in use and then check its status. if its active then do nothing, if its set to In Active(2) or Terminated(3) then we need to log them out. Could anyone give me a start?
I personally haven't tried this, but there's always a first time. You are on the right path of putting this code in a middleware.
php artisan make:middleware CheckUserStatus
Add the newly created middle to your app/Http/kernel.php
protected $routeMiddleware = [
.
.
'status' => \App\Http\Middleware\CheckUserStatusMiddleware::class
]
Inside your CheckUserStatusMiddleware
public function handle($request, Closure $next, $redirectToRoute = null)
{
if ($request->user() && $request->user()->status != 1) {
auth()->logout();
return abort(403, 'Your status is not active anymore.');
}
return $next($request);
}
Lastly, add the middleware to your route call
Route::get('/', 'HomeController#index')->middleware('status');
I'm using Laravel framework my previous version of laravel is 5.8
and in my middleware login
public function handle($request, Closure $next)
{
if(Auth::check())
{
return $next($request);
}
else
{
Session::put('url.intended',URL::previous());
return redirect('/login');
}
}
and this is the controller login controller
if(Session::get('url.intended') <> '')
return Redirect::to(Session::get('url.intended'));
else
return redirect('/');
with this codes in laravel 5.8 everything was working great but when i upgrade to laravel 6 its not working any more i dont know why
any help here thanks
if i came from any link its always redirect me to / link
You should probably be letting the framework handle as much of this as possible. If you must use your own middleware and Controller method still let the framework handle this as it does best.
Dealing with the intended URL is already something the framework is capable of doing itself and checks multiple conditions to figure this out. You can use the guest method of the Redirector to have it do this for you:
return redirect()->guest('login');
This will take care of the redirect to 'login' and set the url.intended in the session as needed.
After login is successful you can redirect them to where they were trying to end up, 'intended', or a fallback url:
return redirect()->intended('/');
This will redirect to what it can find as the 'intended' and if not use a fallback. It will also remove the 'url.intended' key from the session as it is no longer of use. No need to set or check the session yourself.
After following the installation for enabling the new built-in email verification, all is working good (sending email after registration and clicking the activation enable the account).
But, I'm faced with the case where the user must be logged-in in order for the verification process to engage. Meaning, if the user is not logged in prior to use the verification link, he will be redirected to the login page and then be presented the /resources/view/auth/verify.blade.php page.
I am reaching out to the community to see if this it intentional, a bug or something I'm doing wrong? Did someone run in the same situation?
The site I'm setting up have public access to most pages, but restricted to some (for now the user portal). I set up the routes/web.php as follow:
// Authentication
Auth::routes(['verify' => true]);
Route::group(['middleware' => ['auth', 'verified'], 'as' => 'portal.', 'prefix' => '/portal'], function () {
Route::get('/', 'PortalController#index');
Route::get('/profile', 'PortalController#index')->name('profile');
Route::get('/orders', 'PortalController#index')->name('orders');
});
By tracing the verification process, I was able to find out the process is forcing a log-in in the VerificationController constructor via the middleware shown below.
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
By commenting the first line or adding ->except('verify'), the log-in page is not shown but an error is thrown at the Traits VerifiesEmails method Verify like below, since the user is obviously not logged it (the $request->user() is null).
public function verify(Request $request)
{
if ($request->route('id') == $request->user()->getKey() &&
$request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect($this->redirectPath())->with('verified', true);
}
My question, is there a way to get it to work without being loged-in beforehand, or is this the way the Verification process is implemented in 5.7? ... or what am I doing wrong?
is there a way to get it to work without being loged-in beforehand, or
is this the way the Verification process is implemented in 5.7? ... or
what am I doing wrong?
This is the way the Verification process is implemented in Laravel 5.7. Laravel uses signed URLs for verification. The URL is generated with an id parameter (id as user ID) and when the user clicks on the verification link, 3 checks are done:
Is the signature valid? (signed middleware)
What's the user ID in the signature? That's the ID that would ultimately be validated
Does the currently logged in user have the same ID?
You can always remove the third check by overriding the verify method in your VerificationController like so:
public function verify(Request $request)
{
$userId = $request->route('id');
$user = App\User::findOrFail($userId);
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
return redirect($this->redirectPath())->with('verified', true);
}
I am using a session separately other than the default authentication sessions. If an user try to access my secured page, he should have the session set. If anyone without that session try to access means, they will be redirected to error page. I am using Laravel 5.3
The user can view the below two pages only if the session variable named 'secured_user' is set. Otherwise they will be redirect to the error page
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1');
Route::get('/secured-page2', 'ValidationController#CheckSecuredLogin_2');
The best option would be a policy.
You can create certain constrains and couple it with your models. Policies are especially suitable for changing your logic later on.
See here: Create Policy
Within you PagesPolicy, you can add this function:
public function before(User $user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
public function seeSecurePage(User $user)
{
// Your custom Code and session handling
if(session("secured_user")) return true;
return false;
}
and in your controller.
$user->can("seeSecurePage","Pages");
If "can" fails, it will automatically redirect to error 403.
P.S.: Another possibility are Gates
You should use Laravel Middlewares to achieve this, I think middlewares are made for the work you need:
First create a new middleware by running the artisan command:
php artisan make:middleware CheckSesison
Then the CheckSession would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
if ($session_value != 'YOUR_DESIRED_VALUE') {
return redirect('home');
}
return $next($request);
}
}
Now in your routes file you can use laravel's route middleware() method to implement it like this:
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1')
->middleware(CheckSession::class);
Hope this helps!
In addition to the awnser above, you could also use middleware that's used on the routes and even group them if required. It is a simple, quick and clean solution. Inside the middelware you simple check if the session you require is there and depending on the result you take any action necessary.
Laravel middleware docs
For some reason I have had a mind block and can't figure out what is probably a very simple fix.
I have a Laravel 5 App and am using Zizaco's Entrust package for Access Control.
I want to protect a route so am using route Protection in routes.php as follows:
Entrust::routeNeedsRole('passtypes', array('admin'), null, false);
Which works as expected, apart from when a user's session has expired or they are not logged in and try to access the route.
In this case I would want Laravel's Authentication to be checked first, and redirect to the login page; however Entrust redirects to the 403 error first; which is confusing for a user that has ability to view that page, but is told they do not have access, rather than that they are not logged in/session has expired.
I initiate the Authentication in the Controller rather than in the route:
public function __construct()
{
$this->middleware('auth');
}
So just need to know how to get the same functionality, but by having auth get checked before the route permission requirement.
Thanks
I think that Entrust::routeNeedsRole fires before controller. Can you move Entrust to middleware? You could then check in middleware if user is logged in and then check if he has required role.
It's been a while, but I had a similar problem. The only difference, my entire app had to be protected. I ended up modifying Authenticate Middleware handle method:
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
/**
* This is to protect the entire app, except login form,
* to avoid loop
*/
if($request->path() != 'auth/login')
return redirect()->guest('auth/login');
}
}
return $next($request);
}
And inside Kernel.php moved Authenticate from $routeMiddleware to $middleware
Then you can protect your routes with Entrust.