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