Laravel学习笔记之Session源码解析(下)

说明:在中篇中学习了session的CRUD增删改查操做,本篇主要学习关闭session的相关源码。实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介质中;在Response Header中存入cookie。其中,Laravel5.3把垃圾回收提早到了中间件的前置操做,中篇有聊到。OK,学习下关闭session的源码吧先。php

开发环境:Laravel5.3 + PHP7laravel

关闭Session

首先看下\Illuminate\Session\Middleware\StartSession::class中间件源码的handle()方法:ajax

public function handle($request, Closure $next) { ... $response = $next($request); // 检查config/session.php中'driver'是否设置,这里已经假设是redis做为存储介质 if ($this->sessionConfigured()) { // 存储当前URL $this->storeCurrentUrl($request, $session); // 往Response Header中添加cookie $this->addCookieToResponse($response, $session); } return $response; } protected function sessionConfigured() { return ! is_null(Arr::get($this->manager->getSessionConfig(), 'driver')); }

从源码中可知关闭session作了两件事:存储当前URL;往Response Header中添加cookie。redis

OK,先看第一件事:浏览器

// \Illuminate\Session\Middleware\StartSession protected function storeCurrentUrl(Request $request, $session) { // 若是是GET,而且不是ajax,且route对象不能为空 if ($request->method() === 'GET' && $request->route() && ! $request->ajax()) { $session->setPreviousUrl($request->fullUrl()); } } public function setPreviousUrl($url) { // 使用中篇聊到的put()方法更新式存储$url, // 如sentry.app:8888/session,存入到redis中的'laravel:_previous.url' $this->put('_previous.url', $url); }

因此第一件事很简单,OK,看下第二件事:markdown

protected function addCookieToResponse(Response $response, SessionInterface $session) { // No, we use redis as a session handler. if ($this->usingCookieSessions()) { $this->manager->driver()->save(); } // Yes, use redis as the persistent store bucket. if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) { $response->headers->setCookie(new Cookie( // 'laravel_session' $session->getName(), // Str::random(40) $session->getId(), // If it is not set to expire when the browser close. And after 60 minutes, the session will close. $this->getCookieExpirationDate(), // '/session' $config['path'], // 'session_domain' $config['domain'], // true Arr::get($config, 'secure', false), // true Arr::get($config, 'http_only', true) )); } } // 检查是否是cookie存储做为handler,这里是使用redis做为handler protected function usingCookieSessions() { if (! $this->sessionConfigured()) { return false; } return $this->manager->driver()->getHandler() instanceof CookieSessionHandler; } // 检查是否是永久存储,array不是永久存储,这里使用redis是永久存储 protected function sessionIsPersistent(array $config = null) { $config = $config ?: $this->manager->getSessionConfig(); return ! in_array($config['driver'], [null, 'array']); }

第二件事也很简单,实例化Symfony\Component\HttpFoundation\Cookie,并存入到response header中。其中,实例化Cookie所须要的各个参数值为:cookie

(1) $session->getName()session

// $session就是\Illuminate\Session\Store对象

// 在实例化Store对象时,传入的name值是读取的app['config']['session.cookie'] // 见 \Illuminate\Session\SessionManager::buildSession() line 178 'laravel_session' = $session->getName(); 

(2) $session->getId()app

// 在实例化Store时,传入的$id=null,则在Store构造函数中使用setId()设置$id值 //看下Store::setId()源码就知道id是随机生成的长度为40的字符串 Str::random(40) = $session->getId(); public function setId($id) { if (! $this->isValidId($id)) { $id = $this->generateSessionId(); } $this->id = $id; } public function isValidId($id) { return is_string($id) && ctype_alnum($id) && strlen($id) === 40; } protected function generateSessionId() { return Str::random(40); }

(3) $this->getCookieExpirationDate()dom

// config/session.php中默认expire_on_close = false, lifetime = 60 // 表示若是浏览器关闭session不过时,则保留60分钟后再过时 protected function getCookieExpirationDate() { $config = $this->manager->getSessionConfig(); return $config['expire_on_close'] ? 0 : Carbon::now()->addMinutes($config['lifetime']); }

(4) $config['path']

// 默认是'/',这是设置'/session',等会看下响应头 '/session' = $config['path']

(5) $config['domain']

// 这里在config/session.php中设置成'session_domain',等会看下响应头 'session_domain' = $config['domain']

(6) Arr::get($config, 'secure', false)

// 就默认值false false = Arr::get($config, 'secure', false)

(7) Arr::get($config, 'http_only', true)

// 就默认值true true = Arr::get($config, 'http_only', true)

这里输入路由sentry.app:8888/session(在本地环境配置你的路由)简单输出个字符串'session',主要看下响应头是否是设置了配置的cookie值:

看下响应头设置了'laravel_session' cookie,而且'path','domain'是刚刚在session.php中设置的'/session','session_domain'值。总之,Laravel关闭session的第二件事就是给Response Header添加'laravel_session' cookie。

经过对Laravel Session的源码分析可看出Session共分为三大步:启动Session;操做Session;关闭Session。启动Session包括Store实例化,从存储介质中如redis读取session数据,和垃圾回收;操做Session包括对Session的CRUD增删改查操做;关闭Session包括存储当前的URL和往Response Header添加Cookie。

总结:本小系列主要学习了Laravel Session的源码,学习了Session的三大步。后续有好的技术再分享吧,到时见。

相关文章
相关标签/搜索