Laravel禁止返回历史中间件失效:登出后仍可访问仪表盘
解决Laravel登出后可返回管理员仪表盘的问题
我创建了一个名为RevalidateBackHistory.php的禁止返回历史中间件,在kernel.php中注册为**'revalidate'**。该中间件在管理员仪表盘上运行正常,但执行sign out(登出)操作后失效,用户仍可返回仪表盘。我通过Route::group将其应用于整个应用,也尝试过仅配置特定路由,但均未解决问题。
相关代码
中间件代码:
<?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; } }
路由文件web.php:
<?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'); }); });
问题分析与修复方案
核心问题
- 中间件中存在错误的
Cache-Control头设置:$response->headers->set('Cache-Control: post-check=0, pre-check=0', false);这行的键名格式错误,导致缓存头未正确生效。 - 登出操作的响应可能未被中间件正确处理,浏览器仍缓存了仪表盘页面。
修复步骤
1. 修正中间件的缓存头设置
修改RevalidateBackHistory.php的handle方法,合并正确的缓存头参数:
public function handle(Request $request, Closure $next) { $response = $next($request); $response->headers->set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate, post-check=0, pre-check=0'); $response->headers->set('Pragma', 'no-cache'); $response->headers->set('Expires', 'Sun, 02 Jan 1990 00:00:00 GMT'); return $response; }
2. 调整中间件执行顺序
在app/Http/Kernel.php中,将revalidate中间件放在web中间件组的末尾,确保它在所有业务中间件之后执行:
protected $middlewareGroups = [ 'web' => [ // 其他中间件(如EncryptCookies、AddQueuedCookiesToResponse等) \App\Http\Middleware\RevalidateBackHistory::class, ], ];
3. 给登出路由单独加固
在web.php中给登出路由单独添加中间件,确保登出响应强制清除缓存:
Route::get('admin_signout',[AdminController::class, 'signOut'])->name('signout')->middleware('revalidate');
4. 优化登出控制器逻辑
在AdminController的signOut方法中,销毁会话后添加缓存头:
public function signOut() { auth()->guard('admin')->logout(); session()->invalidate(); session()->regenerateToken(); return redirect()->route('login')->withHeaders([ 'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma' => 'no-cache', 'Expires' => 'Sun, 02 Jan 1990 00:00:00 GMT', ]); }
原理说明
通过设置no-cache, no-store等缓存头,强制浏览器每次请求都从服务器获取最新内容,而非读取本地缓存。登出后服务器会验证用户身份,发现未登录则跳转至登录页,此时浏览器点击返回会重新请求页面,而非展示缓存的仪表盘。
内容的提问来源于stack exchange,提问作者merchant8
相关产品推荐
相关产品推荐

