You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel访客页面禁用Session与XSRF-TOKEN Cookie适配Cloudfront缓存

优化Laravel中Cloudfront缓存博客文章的Cookie控制方案

需求说明

  • 运行环境:PHP 8.2,Laravel 11
  • 核心目标:
    • 未登录访客访问博客文章页面(如/posts/news-item-1)时,响应头添加Cache-Control: max-age=3600, public,同时禁用laravel_session和XSRF-TOKEN Cookie,让Cloudfront可缓存静态内容
    • 登录用户访问同一页面时,内容保持私有不缓存,保留Session和Cookie功能
    • 应用其他页面正常维持Session和Cookie机制

现有实现的问题

当前方案通过自定义PageSpeed中间件设置cdn_cache请求参数,再重写VerifyCsrfToken和StartSession核心中间件来控制Cookie生成。虽然功能可用,但重写核心中间件会增加后续版本升级的适配成本,且逻辑分散在多个文件中,维护性较差。

更简洁优雅的实现方案

我们可以通过路由组专属中间件结合Laravel原生扩展点实现,无需重写完整的核心中间件逻辑:

1. 创建缓存控制专属中间件

新建CacheablePublicContent中间件,集中处理缓存规则和Cookie禁用标记:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class CacheablePublicContent
{
    public function handle(Request $request, Closure $next): Response
    {
        // 仅对未登录用户的博客文章路由生效
        if (!Auth::check() && $request->is('posts/*')) {
            // 标记不需要Session Cookie
            $request->attributes->set('skip_session_cookie', true);
            // 标记不需要XSRF Token Cookie
            $request->attributes->set('skip_xsrf_cookie', true);
            
            // 添加Cloudfront缓存响应头
            return $next($request)->header('Cache-Control', 'max-age=3600, public');
        }

        // 登录用户或非博客页面,返回私有缓存头
        return $next($request)->header('Cache-Control', 'private, no-cache');
    }
}

2. 调整VerifyCsrfToken中间件

修改VerifyCsrfToken,利用原生方法判断是否添加XSRF Cookie:

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    public function shouldAddXsrfTokenCookie()
    {
        // 若标记跳过XSRF Cookie,则不生成
        if ($this->request->attributes->get('skip_xsrf_cookie')) {
            return false;
        }

        return parent::shouldAddXsrfTokenCookie();
    }
}

3. 调整StartSession中间件

简化StartSession逻辑,仅在需要时添加Session Cookie:

namespace App\Http\Middleware;

use Illuminate\Session\Middleware\StartSession as Middleware;

class StartSession extends Middleware
{
    protected function addCookieToResponse($response, $session)
    {
        // 若标记跳过Session Cookie,则不添加
        if ($this->request->attributes->get('skip_session_cookie')) {
            return;
        }

        parent::addCookieToResponse($response, $session);
    }
}

4. 绑定中间件到路由组

在routes/web.php中为博客路由组绑定该中间件:

use App\Http\Controllers\PostController;
use App\Http\Middleware\CacheablePublicContent;

Route::middleware(CacheablePublicContent::class)->group(function () {
    Route::get('/posts/{slug}', [PostController::class, 'show'])->name('posts.show');
    // 其他博客相关路由
});

方案优势

  • 逻辑集中:所有缓存控制和Cookie禁用逻辑都在专属中间件中,便于统一维护和调整
  • 低侵入性:仅扩展核心中间件的特定方法,而非重写完整逻辑,降低Laravel版本升级时的适配风险
  • 语义清晰:通过请求属性传递标记,比请求参数更符合Laravel的设计规范

内容的提问来源于stack exchange,提问作者alexmcfarlane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:25:54