企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 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都明白什么是会话了吧。 在这个框架怎样使用它这个会话呢?!