Laravel中如何解决用户登出后按浏览器回退键仍可访问受限页面的问题
问题定位步骤
- 验证中间件是否生效:打开浏览器开发者工具的「网络」面板,访问受保护的后台路由,查看响应头是否存在
Cache-Control、Pragma、Expires三个字段,取值是否符合预期;也可以在中间件的handle方法中加dd('middleware executed');,访问路由时看是否会触发输出。 - 检查中间件执行顺序:当前你的路由组将
prevent-back-history放在auth之前,若auth校验失败跳转登录页,缓存头会被设置到登录页响应上,而非受保护的后台页面。 - 排除历史缓存干扰:未配置中间件前访问过的页面可能已经被浏览器缓存,测试前先清空浏览器缓存,或使用无痕模式验证效果。
- 检查路由覆盖范围:确认所有需要保护的后台路由都已纳入配置了两个中间件的路由组中,未纳入的页面不会生效。
修复方案
- 修正中间件的缓存头拼写错误
你当前代码中Cache-Control的nocache少了横线,属于不符合HTTP标准的写法,部分浏览器不会识别,修改后完整中间件代码如下:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class PreventBackHistory { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { $response = $next($request); $response->headers->set('Cache-Control','no-cache, no-store, max-age=0, must-revalidate, private'); $response->headers->set('Pragma','no-cache'); $response->headers->set('Expires','Sun, 02 Jan 1990 00:00:00 GMT'); return $response; } }
- 调整路由中间件顺序
将auth中间件放在前面,先完成登录校验,再给合法的后台页面响应加缓存头,修改web.php中的路由组配置:
Route::group(['middleware' => ['auth','prevent-back-history']], function() { // 原有路由保持不变 Route::resource('/admins/roles','Admin\RoleController'); Route::resource('/admins/users','Admin\UserController'); Route::resource('/admins/participants','Admin\ParticipantController'); Route::resource('/admins/inqueries','Admin\InqueryController'); Route::patch('/admins/participants/{id}/edit/update', 'Admin\ParticipantController@update')->name('participants.update.update'); Route::patch('/admins/participants/{id}/edit/update_tcp', 'Admin\TakeCarePersonController@update_tcp')->name('participants.update_tcp.update_tcp'); Route::post('/admins/participants', 'Admin\ParticipantController@storetcp')->name('participants.storetcp'); Route::post('/admins/participants/create', 'Admin\ParticipantController@store')->name('participants.store'); });
- 兼容浏览器往返缓存的兜底方案
部分浏览器的bfcache(往返缓存)机制会忽略缓存头直接读取本地快照,可以在后台页面公共的blade布局文件中加入以下JS代码,页面从缓存恢复时自动校验登录状态:
window.addEventListener('pageshow', function(event) { // 页面是从往返缓存中加载的场景 if (event.persisted) { fetch('/user', { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } }).then(res => { if (res.status === 401 || res.status === 419) { window.location.href = '/login'; } }) } });
- 确认登出逻辑正确性
确保登出方法调用了Laravel官方的Auth::logout()逻辑,且会销毁用户会话,避免会话残留导致校验失效。
内容的提问来源于stack exchange,提问作者Old Ceylon Mudliar
相关产品推荐
相关产品推荐

