记laravel的CSRF这个坑

多站点使用 laravel 导致 CSRF 在cookies中的键值冲突,然后爆 Illuminate\Session\TokenMismatchException 错误

问题

这个问题一直间歇性出现,也是最近才意识到因为公司内部各个子站开始推行 laravel

于是重新看了文档找到以下关键

Laravel stores the current CSRF token in a XSRF-TOKEN cookie that is included with each response generated by the framework.

从此可知 laravel 会向 cookies 写入一个键名为 XSRF-TOKEN 的 验证字段,而我们的各站点如果默认都使用此字段就会出现,在A站生成此字段值,在B站使用,然后CSRF报错。

解决

重写 Illuminate\Foundation\Http\Middleware\VerifyCsrfToken 中的 addCookieToResponse 这个方法即可

具体做法

我们只要在 \app\Http\Middleware\VerifyCsrfToken.php 这个文件中,重写此方法即可:

<?php

namespace App\Http\Middleware;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
    ];

    /**
     * Add the CSRF token to the response cookies.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return \Illuminate\Http\Response
     */
    protected function addCookieToResponse($request, $response)
    {
        $config = config('session');

        $response->headers->setCookie(
            new Cookie(
              //在这改成 cookies 中唯一的键即可如 ‘GN_XSRF-TOKEN’
                'XSRF-TOKEN', $request->session()->token(), time() + 60 * $config['lifetime'],
                $config['path'], $config['domain'], $config['secure'], false
            )
        );

        return $response;
    }
}