Laravel学习笔记之Session源码解析(下)
说明:在中篇中学习了session的CRUD增删改查操作,本篇主要学习关闭session的相关源码。实际上,在Laravel5.3中关闭session主要包括两个过程:保存当前URL到session介质中;在Response Header中存入cookie。其中,Laravel5.3把垃圾回收提前到了中间件的前置操作,中篇有聊到。OK,学习下关闭session的源码吧先。
开发环境:Laravel5.3 + PHP7
关闭Session
首先看下\Illuminate\Session\Middleware\StartSession::class中间件源码的handle()方法:
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。
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,看下第二件事:
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所需要的各个参数值为:
(1) $session->getName()
// $session就是\Illuminate\Session\Store对象
// 在实例化Store对象时,传入的name值是读取的app['config']['session.cookie']
// 见 \Illuminate\Session\SessionManager::buildSession() line 178
'laravel_session' = $session->getName();
(2) $session->getId()
// 在实例化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()
// 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的三大步。后续有好的技术再分享吧,到时见。
Laravel学习笔记之Session源码解析(下)的更多相关文章
- Laravel学习笔记之Session源码解析(上)
说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助.Laravel在web middleware中定义了 ...
- Laravel学习笔记之Session源码解析(中)
说明:在上篇中学习了session的启动过程,主要分为两步,一是session的实例化,即\Illuminate\Session\Store的实例化:二是从session存储介质redis中读取id ...
- JUC.Lock(锁机制)学习笔记[附详细源码解析]
锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...
- JUC.Condition学习笔记[附详细源码解析]
目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Condition的数据结构 线程何时阻塞和释放 await()方法 ...
- memcached学习笔记——存储命令源码分析上篇
原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...
- memcached学习笔记——存储命令源码分析下篇
上一篇回顾:<memcached学习笔记——存储命令源码分析上篇>通过分析memcached的存储命令源码的过程,了解了memcached如何解析文本命令和mencached的内存管理机制 ...
- Hadoop学习笔记(10) ——搭建源码学习环境
Hadoop学习笔记(10) ——搭建源码学习环境 上一章中,我们对整个hadoop的目录及源码目录有了一个初步的了解,接下来计划深入学习一下这头神象作品了.但是看代码用什么,难不成gedit?,单步 ...
- Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器解析)
make解析 服务容器对对象的自动解析是服务容器的核心功能,make 函数.build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abstract) ...
- Sping学习笔记(一)----Spring源码阅读环境的搭建
idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...
随机推荐
- 【NOI2005】聪聪和可可 概率与期望 记忆化搜索
1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1635 Solved: 958[Submit][Statu ...
- Codeforces Round #394 (Div. 2) B. Dasha and friends 暴力
B. Dasha and friends 题目连接: http://codeforces.com/contest/761/problem/B Description Running with barr ...
- xcode 拷贝新的ios image 进去以后 出现 the divices is locked
苹果公司时不时的给你更新下ios系统.对于开发者来说.更新xcode是灾难性的. 一直在用xcode7.3.1,可是最新不小心把手机升级到 ios 10.1.1,这下好了,真机调试不行了.提示没有镜像 ...
- 使用 IntraWeb (20) - 基本控件之 TIWGrid
TIWGrid 最终通过 Html Table 呈现; 其每个 Cell 都是一个 TIWGridCell 对象, Cell 对象的 Control 属性非常好, 可以非常方便地嵌入其他控件. TIW ...
- Delphi 资源管理器套件
需要个类似资源管理器的东西, 首先试了下 TDriveComboBox.TDirectoryListBox.TFileListBox, 嘿! Win31 时代的东西, 不是一般地丑. 试了下 Vcl. ...
- MongoDB的Java驱动使用整理 (转)
MongoDB Java Driver 简单操作 一.Java驱动一致性 MongoDB的Java驱动是线程安全的,对于一般的应用,只要一个Mongo实例即可,Mongo有个内置的连接池(池大小默认为 ...
- 【Go命令教程】5. go clean
执行 go clean 命令会删除掉执行其它命令时产生的一些文件和目录,包括: 在使用 go build 命令时在当前代码包下生成的与包名同名或者与Go源码文件同名的可执行文件.在Windows下,则 ...
- C#实现路由器断开连接,更改公网ip
publicstaticvoid Disconnect() { string url ="断 线"; string uri ="http://192.168.1.1 ...
- bat如何批量删除指定部分文件夹名的文件夹
@echo offfor /f "delims=" %%i in ('dir /s/b/ad 123*') do ( rd /s/q "%%~i")exit
- lufylegend:加载进度
实现图片加载进度 LoadingSample Class 用来显示进度条的对象. 引擎中目前提供的进度条类有:LoadingSample1-7 你可以制作自己的进度条,自制进度条类中要包含setPro ...