I made a prevent back history middleware named RevalidateBackHistory.php, registered into kernel.php as 'revalidate'. This middleware is working on admin dashboard perfectly but when I sign out, it's not working, user can go back to the dashboard. I implemented this middleware on the whole application using Route::group and also tried to implement this on specific routes, but no luck. Thanks in advance.
Here's the code for the middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class RevalidateBackHistory
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$response = $next($request);
$response->headers->set('Cache-Control','no-cache, no-store, max-age=0, must-revalidate');
$response->headers->set('Cache-Control: post-check=0, pre-check=0', false);
$response->headers->set('Pragma','no-cache');
$response->headers->set('Expires','Sun, 02 Jan 1990 00:00:00 GMT');
return $response;
}
}
Here's my web.php(routes):
<?php
use App\Http\Controllers\AdminController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\StoreController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ReviewController;
use App\Http\Controllers\CartController;
use App\Http\Controllers\PayPalController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| 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::group(['middleware' => 'revalidate'], function() {
//Store Routes
Route::get('store',[StoreController::class, 'index'])->name('store');
Route::get('/', function () {return redirect()->route('store');});
//Single Product Page
Route::get('show/{id?}',[StoreController::class, 'show'])->name('show');
//Cart Functionalities
Route::get('cart',[CartController::class, 'cart'])->name('cart');
Route::post('add-to-cart', [CartController::class, 'addToCart'])->name('add-to-cart');
Route::get('load-cart-data',[CartController::class, 'cartLoadAjax'])->name('load-cart-data');
Route::post('update-cart-data',[CartController::class, 'updateCartData'])->name('update-cart-data');
//Redirect if already authenticated middleware(Admin)
Route::group(['middleware' => ['auth:web']], function() {
//Checkout
Route::get('checkout',[StoreController::class, 'checkOut'])->name('checkout');
//Create Comment
Route::post('comments/{id}',[ReviewController::class, 'store'])->name('comment');
//Paypal
Route::post('payment', [PayPalController::class, 'payment'])->name('payment');
Route::get('payment.success', [PayPalController::class, 'success'])->name('payment.success');
//getDetails
Route::get('get.details', [UserController::class, 'getDetails'])->name('get.details');
});
//Redirect if already authenticated middleware(Admin)
Route::group(['middleware' => ['guest:web']], function() {
//User Login and Registration
Route::get('UserLogin',[UserController::class, 'UserLogin'])->name('UserLogin');
Route::post('user.login',[UserController::class, 'UserCustomLogin'])->name('user.login');
Route::post('UserRegis',[UserController::class, 'customUserRegistration'])->name('UserRegis');
});
Route::group(['middleware' => ['guest:admin']], function() {
//Admin Register
Route::get('admin_register',[AdminController::class, 'registration'])->name('GetSignUp');
Route::post('post_Register',[AdminController::class, 'customRegistration'])->name('aSignUp');
//Admin Login
Route::get('admin_login',[AdminController::class, 'AdminGetLogin'])->name('login');
Route::post('post_login',[AdminController::class, 'CustomLogin'])->name('aAuth');
});
Route::group(['middleware' => ['auth:admin']], function() {
// define your route, route groups here
//Dashboard
Route::get('dashboard',[AdminController::class, 'dashboard'])->name('dashboard');
//SignOut
Route::get('admin_signout',[AdminController::class, 'signOut'])->name('signout');
//Products
Route::get('add_product',[ProductController::class, 'create'])->name('add_product');
Route::post('save_product',[ProductController::class, 'createProduct'])->name('save_product');
Route::get('view_products',[ProductController::class, 'viewProducts'])->name('view_products');
//New Edit
Route::get('editNew/{id?}',[ProductController::class, 'editNew'])->name('editNew');
//Update Product Data
Route::post('update_product/{id}',[ProductController::class, 'update'])->name('update_product');
//Delete Product
Route::delete('/delete_product/{id}',[ProductController::class, 'destroy'])->name('delete_product');
//Search Product
Route::get('search',[ProductController::class, 'search'])->name('search');
});
});
Can you try and set it as a global middleware in your App\Http\Kernel.php
The application's global HTTP middleware are run during every request to your application.
Hope that helps.
Related
I'm doing some tests with Middleware to prevent the user not logged into the system from accessing pages that only logged in people can access. Apparently when I enter http://127.0.0.1:8000/fighter it returns to http://127.0.0.1:8000/login.
The problem occurs that when logging in I am redirected to http://127.0.0.1:8000/fighter and not to http://127.0.0.1:8000/dashboard which would be the correct.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FighterController;
use App\Http\Controllers\MasterController;
use App\Http\Controllers\DojoController;
/*
|--------------------------------------------------------------------------
| 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('welcome');
});
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
// fighter folder
Route::middleware('auth')->group(function(){
Route::controller(FighterController::class)->group(function() {
Route::get('/fighter', 'index')->name('fighter.index');
Route::get('/add-fighter', 'create')->name('fighter.create');
Route::post('/add-fighter', 'store')->name('fighter.store');
Route::get('/update-fighter/{id}', 'edit')->name('fighter.edit');
Route::patch('/update-fighter/{id}', 'update')->name('fighter.update');
Route::delete('/delete-fighter/{id}', 'destroy')->name('fighter.destroy');
});
});
// master folder
Route::middleware('auth')->group(function(){
Route::controller(MasterController::class)->group(function() {
Route::get('/master', 'index')->name('master.index');
Route::get('/add-master', 'create')->name('master.create');
Route::post('/add-master', 'store')->name('master.store');
Route::get('/update-master/{id}', 'edit')->name('fighter.edit');
Route::patch('/update-master/{id}', 'update')->name('fighter.update');
Route::delete('/delete-master/{id}', 'destroy')->name('fighter.destroy');
});
});
// dojo folder
Route::middleware('auth')->group(function(){
Route::controller(DojoController::class)->group(function() {
Route::get('/dojo', 'index')->name('dojo.index');
Route::get('/add-dojo', 'create')->name('dojo.create');
Route::post('/add-dojo', 'store')->name('dojo.store');
Route::get('/update-dojo/{id}', 'edit')->name('dojo.edit');
Route::patch('/update-dojo/{id}', 'update')->name('dojo.update');
Route::delete('/delete-dojo/{id}', 'destroy')->name('dojo.destroy');
});
});
require __DIR__.'/auth.php';
I'm just learning laravel and now i'm stuck at Middleware stuff. I have class AdultMiddleware.php :
<?php
namespace App\Http\Middleware;
use Closure;
class AdultMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Session::get('age') < 18) {
return view('search');
}
return $next($request);
}
}
and it's short name in Kernel.php :
protected $routeMiddleware = [
'adult' => \App\Http\Middleware\AdultMiddleware::class,
];
And in web.php :
Route::get('middle', array('as' => 'middle', 'age' => '16', 'before' => 'adult', function()
{
return view('welcome');
}));
As you see in routes I set age as 16 , but still it returns welcome instead of search. What I'm doing wrong? I know it may sound newbie, but I did try to google and had no luck. That's why I'm asking here.
Assigning middleware to a route:
Route::get(..., ['middleware' => 'adult', ...]);
Route::get(..., ...)->middleware('adult');
before is for filters which don't exist any more in Laravel since middleware replaced filters.
Route::get('middle', ['as' => 'middle', 'middleware' => 'adult', function () {
return view('welcome');
}]);
Laravel Docs - 5.2 - Middleware - Assigning Middleware to routes
Laravel Docs - 5.5 - Middleware - Assigning Middleware to routes
If your middleware is going to check a session variable, you could add a route to be able to set that session variable as you like.
Route::get('set/age/{age}', function ($age) {
session(['age' => $age]);
return redirect()->route('middle');
});
That will set the age variable in the session and redirect you to your 'middle' route.
Also you may want to return a redirect to the search page instead of returning a view from the middleware.
I want to prevent the user from clicking back the browsers button. Whenever user logged in and click browser's back button the page redirect back to login which is wrong. I create middleware and register it to the kernel and use it in my route as group but its not working. Here's the code
MIDDLEWARE
<?php
namespace App\Http\Middleware;
use Closure;
class ClearCache
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set("Cache-Control", "no-cache,no-store, must-revalidate");
return $response;
}
}
KERNEL
protected $routeMiddleware = [
....
// CUSTOM MIDDLEWARE GOES HERE
'clear.cache' => \App\Http\Middleware\ClearCache::class,
];
ROUTES
<?php
Route::group(['middleware' => 'guest'], function() {
Route::get('/', function () {
return view('welcome');
});
});
Auth::routes();
Route::group(['middleware' => 'auth'], function() {
Route::group(['middleware' => 'clear.cache'], function() {
Route::get('/home', 'HomeController#index');
});
});
After logging in when user clicks back button it redirects back on login page. Logged out is fine. Any help? :(
You can define multiple middleware for one group :
Route::group(['middleware' => ['auth', 'cache.clear']], function() {
But by default Laravel redirects users to $redirectTo defined in your Auth controllers. I don't understand why you are trying to avoid back click.
I'm still very noobish with Larvel, so i can't figure out how to do this:
I'm stuck at the login system. I'm trying to understand how i can prevent inactive users to use the application.
Edit
With inactive users i mean those users which has the record field 'active' on 0. So i need to implement a check which verifies the mail and the password and also the active field
I've made the tables and the auth system, and as written in the documentation, I've placed this method inside my AuthController:
public function authenticate()
{
dd('hi');
}
Well it completely gets ignored. It seems like it never gets triggered. Am I missing something?
My controller looks like the original Laravel's 5.2 AuthController except for the method before. No other changes has been made, since according to the documentation no other changes are mentioned...
My tests:
I've also searched for a method called authenticate. But no methods where found (using php storm). So my question is:
If it's a trait, isn't supposed to have that method declared? So i can override it just by declaring a method with the same name?
Important files:
Routes.php
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/', 'HomeController#index');
Route::auth();
Route::get('/home', 'HomeController#index');
SOLVED
If you type php artisan route:list you see when login by post method, user post their info account to login action in LoginController. So, I've solved the problem by override login method in Auth\LoginController as below:
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
$credentials['active'] = 1;
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect()->intended('/');
}
}
Firstly you need to remove the Auth routes but before that run php artisan route:list in your terminal. Copy the auth related routes and stick them in your routes file.
Change the controller in each of the routes to point to your own AuthController in your application.
Next, include the following 2 traits into your controller (top of the page) plus 2 classes;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
and then include the traits in the top of your class;
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
as it stands, the auth functionality should still work as normal.
Then, alter the login method to accept an active flag. Add the following to your new controller;
/**
* [login description]
* #param Request $request [description]
* #return [type] [description]
*/
public function login( Request $request, $guard )
{
$this->validateLogin( $request );
$throttles = $this->isUsingThrottlesLoginsTrait();
if ( $throttles && $lockedOut = $this->hasTooManyLoginAttempts( $request ) ) {
$this->fireLockoutEvent( $request );
return $this->sendLockoutResponse( $request );
}
$credentials = $this->getCredentials( $request );
if ( Auth::guard( $guard )->attempt( [ 'active' => 1 ] + $credentials, $request->has( 'remember' ) ) ) {
return $this->handleUserWasAuthenticated( $request, $throttles, $guard );
}
// check to see if they can login without the active flag
if( Auth::guard( $guard )->attempt( $credentials ) ) {
// log them back out and send them back
Auth::guard( $guard )->logout();
return redirect()->back()
->withInput( $request->only( $this->loginUsername(), 'remember' ) )
->withErrors([
'active' => 'Your account is currently not active',
]);
}
if ( $throttles && ! $lockedOut ) {
$this->incrementLoginAttempts( $request );
}
return $this->sendFailedLoginResponse( $request );
}
using the traits in your own controller should give you more flexibility in the future.
regards
To prevent guest users (not authenticated) to access certain routes, you should protect those routes in your routes.php:
// All the routes inside the group are accessible for logged in users only
Route::group(array('before' => 'auth'), function() {
Route::get('myroute', 'Controller#action');
});
// For routes accessible for everybody
Route::get('login', function(){
return View::make('login');
});
Solved
I've managed to do this by myself. Not sure that is the proper way, but anyway it works.
I've decided to create a middleware that after the successful login, checks that the user 'active' field is 1. If not it redirects to a specific page.
public function handle($request, Closure $next)
{
// If the user is not logged in
if(!Auth::user()){
return redirect('login');
}
// If the user is inactive
if(!Auth::user()->active){
return redirect('inactive');
}
return $next($request);
}
I've started learning Laravel 5.1 and so far I'm liking it! But there is one thing I don't get yet..
In my previous project I had 2 specific controllers (eg: "normal", "extended") which , after a successfull login, were called based on the Users user_group from the database.
If "Foo.Bar" enters his valid credentials and has the group normal he is redirected to NormalControler. Since I wasn't using any framework I restricted access to the other group by setting a $_SESSION with the group and checking it. So if another group tried to access that controller he got redirected.
How would this be achievable in Laravel 5? So far I have a controller which is callable without an Authentication and one restricted by this code in routes.php :
// All routes in the group are protected, only authed user are allowed to access them
Route::group(array('before' => 'auth'), function() {
// TO-DO : Seperate Controller access
});
And the login looks like this :
public function performLogin()
{
$logindata = array(
'username' => Input::get('user_name'),
'password' => Input::get('user_pass')
);
if( Auth::attempt( $logindata ) ){
// return \Redirect::to( check group and access this controller based on it);
}
else {
// TO-DO : Redirect back and show error message
dd('Login failed!');
}
}
----- EDIT -----
I've run the artisan command and made this middleware as you suggested :
namespace App\Http\Middleware;
use Closure;
use Request;
class GroupPermissions
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $group)
{
// Check User Group Permissions
if( $request->user()->group === $group ){
// Continue the request
return $next($request);
}
// Redirect
return redirect('restricted');
}
}
and edited this line into Kernel.php into $routeMiddleware :
'group.perm' => \App\Http\Middleware\GroupPermissions::class
I think this is done right so far, correct me if I'm wrong! Could I then do something like this to restrict the controllers?
Route::group(array('before' => 'auth'), function() {
Route::group( ['middleware' => 'group.perm', 'group' => 'normal'], function(){
Route::get('/normal/index', 'DummyNormalController#index');
});
Route::group( ['middleware' => 'group.perm', 'group' => 'extended'], function(){
Route::get('/extended/index', 'DummyExtendedController#index');
});
});
Ok, here is what you might do. Once user is logged in, you would check his credentials, get his user_group and decide what controller he should be redirected to.
if( Auth::attempt( $logindata ) ){
$user = Auth::user();
if ($user->inGroup('normal')) {
return redirect()->route('normal_controllers_named_route');
}
return redirect()->route('extended_controllers_named_route');
}
return redirect()->back()->withFlashMessage('don\'t get me wrong');
This will handle right routing after logging in.
The next portion where you need to protect you routes from unwanted user groups may be achieved with middlewares.
do an artisan command php artisan make:middleware ShouldBeInGroup
go to app/http/Kernel.php and add your new middleware to the routeMiddleware array. Key of the item might be anything you like. Let's call in inGroup. So: 'inGroup' => 'App\Http\Middleware\ShouldBeInGroup'
Now, in your controller, in constructor, you are able to call this middleware
$this->middleware('inGroup:extended'); //we also passing the name of the group
at lastly, work on the our middleware. Open newly created ShouldBeInGroup class and edit the handle method.
public function handle($request, Closure $next, $groupName)
{
if (Auth::check() && Auth::user()->inGroup($groupName)) {
return $next($request);
}
return redirect('/');
}
And finally you should work on inGroup method, that should return true of false. I assume that you have user_group field your users table. Then in your User eloquent model add the method
public function inGroup($groupName) {
return $this->user_group == $groupName;
}
Edit
if you want to use this middleware in your routes, you can do the following
Route::group(array('before' => 'auth'), function() {
Route::get('/normal/index', ['middleware' => 'group.perm:normal', 'uses' =>'DummyNormalController#index']);
}
But generally it's better to put all your middlewares into your Controller's constructor
public function __construct(){
$this->middleware('group.perm:normal'); // you can also pass in second argument to limit the methods this middleware is applied to : ['only' => ['store', 'update']];
}
And also on this note, Laravel provides built in auth middleware that you can use
public function __construct(){
$this->middleware('auth');
$this->middleware('group.perm:normal');
}
so then your routes would become much cleaner, just:
Route::get('normal/index', 'DummyNormalController#index');
I think the best way to do that is using middlewares. See the doc here
You can easily create a middleware using the following artisan command:
php artisan make:middleware ExtendedMiddleware
If you can't or don't want to use artisan, you need to create a class in The App/Http/Middleware folder.
In this class you'll need the following method to handle the request. In the method you can check for the user group.
public function handle($request, Closure $next)
{
// check user group
if( user_group_ok )
return $next($request); // Continue the request
return redirect('restricted'); // Redidrect
}
You can then use this middleware in your route.php file:
Route::group(['middleware' => 'auth'], function()
{
// Logged-in user with the extended group
Route::group(['middleware' => 'extended'], function()
{
// Restricted routes here
});
// Normal routes here
});
You can create a Middleware called : PermissionFilter
In PermissionFilter, you check if requesting user is in the group or not.
I can't provide a demo for now, but if you want I can make a demo later.
L5 middleware: http://laravel.com/docs/5.1/middleware