laravel的cookie是怎么产生的?

背景:

laravel大家都经常用,cookie也都不陌生,但是你真的知道laravel的cookie是怎么产生的吗?

 

一、cookie是怎么响应到客户端的?

cookie通过addCookieToResponse方法添加到Response,这个方法定义在src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php

 

二、addCookieToResponse响应了什么样的cookie?

来看看addCookieToResponse的代码逻辑:

    protected function addCookieToResponse($request, $response)
    {
        $config = config('session');

        if ($response instanceof Responsable) {
            $response = $response->toResponse($request);
        }

        $response->headers->setCookie(
            new Cookie(
                'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
                $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
            )
        );

        return $response;
    }

我们需要重点看的是下面这段,这也是产生cookie的关键所在:

        $response->headers->setCookie(
            new Cookie(
                'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
                $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
            )
        );

 cookie是由new Cookie产生的,那么,构造new Cookie的参数都代表什么呢?

Cookie定义在vendor/symfony/http-foundation/Cookie.php,构造函数如下:

    public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax')
    {
        // from PHP source code
        if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) {
            throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
        }

        if (empty($name)) {
            throw new \InvalidArgumentException('The cookie name cannot be empty.');
        }

        $this->name = $name;
        $this->value = $value;
        $this->domain = $domain;
        $this->expire = self::expiresTimestamp($expire);
        $this->path = empty($path) ? '/' : $path;
        $this->secure = $secure;
        $this->httpOnly = $httpOnly;
        $this->raw = $raw;
        $this->sameSite = $this->withSameSite($sameSite)->sameSite;
    }

 据此,不难看出,laravel的cookie以header的方式响应到客户端,header对应的key是XSRF-TOKEN,对应的value是$request->session()->token(),cookie的有效期由config下的lifetime参数决定

 

到这里,其实我们已经知道了laravel的cookie产生及响应到客户端的大致过程,但是这还不够具体,我们进一步分析$request->session()->token()

cookie的value由$request->session()->token()而来,也就是说cookie的value,本质上是session的token,那么session的token又是怎么产生的呢?

laravel的Session是由Store类实现的,Store类定义在src/Illuminate/Session/Store.php,在这个文件里,有一个token()方法,代码逻辑如下:

    public function token()
    {
        return $this->get('_token');
    }

token是由_token得到的,而这个_token由regenerateToken方法实现,代码逻辑如下:

    public function regenerateToken()
    {
        $this->put('_token', Str::random(40));
    }

 Session的_token,是由Str::random产生的,这也就是cookie的value产生的根源了,如果对Str::random不了解,可以参考我之前的博客,有专门的介绍。

 

总结:

laravel的cookie,本质上是Session的_token,而Session的_token,是由Str::random随机产生的长度为40的随机字符串,cookie被添加到Response的header头里,cookie的header是XSRF-TOKEN

posted @ 2022-04-29 23:51  jamstack  阅读(205)  评论(0编辑  收藏  举报