# Sessions(会话)
HTTP是一个无状态协议,但几乎每个应用程序都需要在请求之间存储状态。 购物车的内容 正是为了会话(或关系)是。 这章主要学会以下几点
* 怎样使用Sessions
* 怎样避免命名冲突
* 设置Sessions过期时间
* 怎样安全抵御漏洞
使用会话时,每个访问网页的用户都会收到一个唯一的会话ID标识符,该标识符由Cookie传递。 它用作会话数据的键。 它与存储在浏览器端的Cookie不同,会话数据存储在服务器端。
# Sections(部分)
在纯PHP里会话数据存储为一个数组,可通过全局变量$ _SESSION访问。 问题是,应用程序通常由几个独立的部分组成,如果每个部分都可以使用相同的数组,你必须及早解决命名冲突。
Nette框架通过将会话空间划分为段(Nette \ Http \ SessionSection对象)来解决这个问题。 因此,一个程序的每个部分都使用它自己的部分具有唯一的名称,并且不会发生冲突。
让我们从会话管理器开始,这是Nette \ Http \ Session类的一个对象。 我们可以直接从控制器访问此服务:
~~~
// $this stands for presenter
$session = $this->getSession();
$mySection = $this->getSession('mySection');
~~~
或者我们可以要求在我们的构造函数中使用依赖注入:
~~~
use Nette;
class MyService {
/** @var Nette\Http\Session */
private $session;
/** @var Nette\Http\SessionSection */
private $sessionSection;
public function __construct(Nette\Http\Session $session)
{
$this->session = $session;
// get section by identifier 'mySection':
$this->sessionSection = $session->getSection('mySection');
}
}
~~~
我们可以使用一个方法hasSection('myCounter')来检查变量的存在。
没有必要启动或关闭该会话,它是由框架本身自动完成。 但是我们可以通过调用$ session-> start()手动启动它。 如果我们多次调用start()方法,没有什么发生,它将没有效果。 您还可以在配置中修改此行为。
然后,使用该部分非常简单:
~~~
// variable writing
$section->userName = 'franta'; // or $section['userName'] = 'franta';
// variable reading
echo $section->userName; // or echo $section['userName'];
// variable cancellation
unset($section->userName); // unset($section['userName']);
~~~
可以使用foreach循环从section获取所有变量:
~~~
foreach ($section as $key => $val) {
echo "$key = $val";
}
~~~
## 示例:访问计数器
我们将从访问计数器的示例开始,其中显示用户显示页面的次数。
~~~
$section = $container->getService('session')->getSection('myCounter');
$section->count++; // increment counter by one
echo "You displayed this page $section->count ×";
~~~
访问不存在的变量不会生成错误(变量具有NULL值)。 在某些情况下,这可能是不希望的行为,这就是为什么有可能改变它:
~~~
$section->warnOnUndefined = TRUE;
~~~
## 如何设置过期时间
非常有用的功能是为每个部分或变量设置自己的过期时间的可能性。 所以我们可以让用户登录,但仍记得购物车的内容。
~~~
// section will expire after 2 minutes
$section->setExpiration('2 minutes');
// variable $section->a will expire after 10 seconds
$section->setExpiration(10, 'a');
~~~
除了相对时间(以秒为单位),可以使用UNIX时间戳或文本形式。 有趣的是值为0,它设置到用户关闭浏览器时的到期时间:
~~~
// variable $section->password will expire when a user closes a browser
$section->setExpiration(0, 'password');
~~~
请记住,整个会话的过期时间(请参阅会话配置)必须等于或大于为单独的段或变量设置的时间。
可以通过调用remove Expiration()方法来取消先前设置的到期。 立即取消整个段由remove()方法处理。
## 会话配置
会话的配置必须在使用之前完成。 最好的地方是config.neon。
要配置什么? 过期时间。 如果未进行此设置,则每次会话变量将在浏览器窗口关闭时过期。 在窗口关闭之后存储会话对于例如长时间用户登录是有用的。
~~~
session:
expiration: 14 days
~~~
您还可以配置会话自动启动。
~~~
session:
autoStart: true # 'smart' is default value
~~~
如果您使用共享主机,则适合使用自定义目录来存储具有会话关系的文件:
~~~
session:
savePath: "%tempDir%/sessions"
~~~
在这种情况下,%tempDir%将替换为您在bootstrap.php中的$ configurator-> setTempDirectory()中设置的值。
如果你想扩展子域的会话(或认证)的有效性,让我们设置另一个cookie参数:
~~~
// sets cookie validity for all subdomains
$session->setCookieParameters('/', '.example.com');
session:
cookiePath: '/'
cookieDomain: '.example.com'
~~~
## 安全第一
服务器假定它与同一用户通信,只要请求包含相同的会话ID。 安全机制的任务是确保这种行为真正有效,并且不可能替换或窃取标识符。
这就是为什么Nette框架正确配置PHP指令只在cookie中传输会话ID,以避免从JavaScript访问和忽略URL中的标识符。 此外,在关键时刻,例如用户登录,它生成一个新的会话ID。
函数ini_set用于配置PHP,但不幸的是,它的使用是禁止在某些网络托管服务。 如果是这样,请尝试请您的托管提供商为您允许此功能,或至少正确配置其服务器。
## 已知限制
在Chrome浏览器的“系统”部分中,Chrome浏览器关闭时继续运行后台应用,此选项默认为启用。 它导致具有设置过期的cookie关闭浏览器,cookie仍然存在。 截至到期0,当关闭浏览器时不会被删除。
小章总结:
这章主要教大家学会用session(),学会PHP都明白什么是会话了吧。
在这个框架怎样使用它这个会话呢?!
- Nette简介
- 快速开始
- 入门
- 主页
- 显示文章详细页
- 文章评论
- 创建和编辑帖子
- 权限验证
- 程序员指南
- MVC应用程序和控制器
- URL路由
- Tracy - PHP调试器
- 调试器扩展
- 增强PHP语言
- HTTP请求和响应
- 数据库
- 数据库:ActiveRow
- 数据库和表
- Sessions
- 用户授权和权限
- 配置
- 依赖注入
- 获取依赖关系
- DI容器扩展
- 组件
- 字符串处理
- 数组处理
- HTML元素
- 使用URL
- 表单
- 验证器
- 模板
- AJAX & Snippets
- 发送电子邮件
- 图像操作
- 缓存
- 本土化
- Nette Tester - 单元测试
- 与Travis CI的持续集成
- 分页
- 自动加载
- 文件搜索:Finder
- 原子操作