1、Session vs. Cookie

与 Cookie 一样,Session 技术也是用于解决 HTTP 协议无状态的问题,不过,与 Cookie 数据保存在客户端不同,Session 数据存储在服务端,然后通过分配一个全局唯一的 ID 与特定用户关联(通常在用户认证通过后分配),但 Session 又与 Cookie 紧密关联,因为这个 Session ID 通常会存储到 Cookie 中,在其生命周期内,用户发起请求时就会带上它,这样服务端通过解析存储在 Cookie 中的 Session ID 就能识别特定的客户端用户,并返回与之关联的 Session 数据,比如前面提到的电商网站中的购物车数据。

注:虽然 Session ID 也可以包含在 URL 请求参数(查询字符串)中,但是维护成本太高,不如直接存储到 Cookie 中方便,所以渐渐废弃,现在基本上都是通过 Cookie 存储,并以此建立服务端与客户端的关联和用户认证状态的维护。

2、Session 运行原理和配置浅析

Session 技术的一个主要用途就是用户认证,其基本实现原理是在用户登录成功后为其生成一个全局唯一的 Session ID,并且将必要的用户会话数据存储到服务端对应的 Session 数据中(后续可通过 Session ID 查询),然后通过 Set-Cookie 响应头将 Session ID 发送到客户端,并存储到客户端 Cookie,过期时间与服务端维护的 Session 有效期一致(默认是 3 小时),在 Session 有效期内,所有客户端请求都会自动通过 Cookie 请求头带上这个 Session ID,服务端解析到这个 Session ID 并且查询对应 Session 数据存在,则表明该客户端用户是一个已认证用户,进而返回对应的用户信息该客户端,让客户端可以标识对应用户的登录状态。

注:除了用户认证之外,Session 还有一些其他的使用场景,比如验证码校验、存储一些其他的用户状态信息(比如限定访问频率、禁止重复提交表单等)。

另外,在服务端,Session 数据默认存储在文件中,这是通过 php.inisession.save_handler 配置项配置的:


你还可以通过 session.save_path 指定存储 Session 数据文件的路径(默认是 /tmp,该配置仅在 session.save_handlers 值为 files 时有效),另外,在上述代码中,还可以看到与 Cookie 相关的配置:


当我们基于 Cookie 存储 Session ID 时,会通过这个配置项设置对应的 Cookie 属性,通过下面两个配置可以看到默认就是基于 Cookie 保存 Session ID,并且只使用 Cookie 保存(1 表示 true):


并且这个存储在 Cookie 中的 Session ID 对应名称是 PHPSESSID

PHPSESSID => PHPSESSID

最后,Session 功能默认是关闭的,如果要使用 Session 需要主动开启,Session 默认的有效期是 3 个小时(通过 cache_expire 配置项配置,单位为分钟),3 小时后自动销毁:


当然,以上配置在运行时都是支持动态设置的。

3、Session 的基本使用

我们以用户认证为例,演示下如何在 PHP 中使用 Session。

基本增删改查演示

首先我们来简单看下如何启用并设置/读取 Session 数据,在 php_learning/http 目录下新建 session.php

<?php session_save_path('./session');session_start();if (isset($_SESSION['name'])) {echo $_SESSION['name'];exit();}$_SESSION['name'] = '学院君';

我们调用 PHP 内置的 session_save_path 函数设置 Session 存储目录为当前目录下的 session 子目录中,然后调用 session_start 函数启动 Session(这一行代码最为关键,不能省略,否则无法使用 Session 保存和读取数据)。

接下来,我们就可以通过 PHP 超全局变量 $_SESSION 读取和设置 Session 数据了,和之前的其他超全局变量一样,$_SESSION 也是一个关联数组,通过关联数组的方式更新或者新增 Session 数据即可,如果要删除某个 Session 数据,使用 unset 函数即可:

unset(

我们在浏览器中访问 http://localhost:9000/session.php,首次访问没有任何输出,因为 Session 中还没有数据,但是再次刷新就可以看到 Session 中的数据被打印出来:


此时看 http/session 目录下,已经包含生成的 Session 数据文件了:


并且在浏览器中,也可因看到 Cookie 中包含了对应的 PHPSESSID Cookie:


这个就是服务端自动生成并发送到客户端 Cookie 的 Session ID,这些逻辑都有 PHP 底层自动维护,我们不必关心。

4、实现简单的用户登录功能

接下来,我们来基于 Session 在 PHP 代码中实现简单的用户认证。

登录页面

首先将 http/form.html 重命名为 form.php,并加入错误提示(如果有的话),将表单提交链接调整为 login.php

html>

...

class="container col-4">
    <h1 class="text-center">登录表单h1>php if (!empty($error)): ?>
        <div class="alert alert-danger" role="alert">
            = $error ?>div>php endif; ?>
    <form method="post" action="login.php">
        <div class="form-group">
            <label for="name">用户名label>
            <input type="text" class="form-control" name="name" id="name">div>
        <div class="form-group">
            <label for="password">密码label>
            <input type="password" class="form-control" id="password" name="password">div>
        <button type="submit" class="btn btn-primary">登录button>form>div>body>html>

用户登录处理

然后我们在 http 目录下新建一个 login.php 编写用户登录处理代码:

<?php session_save_path('./session');session_start();// 模拟数据库数据$data = [    ['id'  => 1,'name' => '测试账号','password' => '123456'    ],    ['id'  => 2,'name' => '学院君','password' => '123456'    ]];if ($_SERVER['REQUEST_METHOD'] == 'POST') {    $name = $_POST['name'];    $password = $_POST['password'];if (empty($name) || empty($password)) {        $error = '用户名/密码不能为空,请重试';    } else {// 简单模拟用户名和密码是否匹配        $user = array_filter($data, function ($item) use ($name, $password) {if ($item['name'] == $name && $item['password'] == $password) {return true;            }return false;        });if (!empty($user)) {            $_SESSION['user'] = array_shift($user);            header('Location: /user.php');        } else {            $error = '用户名/密码不正确,请重试';        }    }}include_once 'form.php';

开头两行代码还是 Session 初始化设置和启动,然后通过数组模拟数据库用户数据,接下来,如果是 GET 请求,直接通过 include_once 'form.php' 渲染登录表单页面,如果是 POST 请求,则通过 $_POST 读取表单输入,如果用户名密码为空或者在「数据库」中不存在,则返回对应的错误提示信息,让用户重新输入并提交表单,否则在 $_SESSION['user'] 中设置对应的用户信息,并将用户重定向到 user.php 页面显示登录用户信息。

显示用户信息

最后,我们在 http 下新建 user.php,然后在其中编写登录用户信息展示代码:

<?php session_save_path('./session');session_start();if (isset($_SESSION['user'])) {    header('Content-Type: application/json');    $user = $_SESSION['user'];echo json_encode($user);} else {    header('HTTP/1.1 401 Unauthorized');echo '登录后才能访问: 立即登录';}

开始还是要初始化和启动 Session(这块代码可以独立出去,然后通过 require 引入,从而方便代码复用),这里为了简化业务逻辑,直接返回包含用户信息的 JSON 数据,如果用户 Session 数据为空,表示该用户尚未登录,返回 401 响应,并提示用户点击登录链接登录。

注:这里,读取 Cookie 中的 Session ID 并与服务端对应的 Session 数据映射由 PHP 系统底层完成,上层业务开发人员不需要关心其细节。

测试用户登录功能

现在,我们访问 http://localhost:9000/user.php,会提示我们需要登录:


点击登录链接,即可进入登录页面,如果输入的登录账号和密码不正确,会提示重新输入:


如果登录成功,则会跳转到 http://localhost:9000/user.php 返回登录用户信息:


感兴趣的同学可以自行实现对应的用户退出逻辑(清除保存用户登录信息的 Session 即可)。

小结

至此,我们就完成了 PHP 中 Web 开发(HTTP 编程)相关的所有基础知识的介绍,包括服务器、请求处理、HTTP响应、Cookie 和 Session,再结合之间的 PHP 基础知识、面向对象编程、数据库操作,我们就已经可以开发出常见的 Web 应用了,从下篇教程开始,我们将结合上述基础知识编写一个简单 PHP Web 框架(MVC 模式),有了这个过渡,相信大家再去看 Laravel 的设计和实现就更加得心应手了。

(全文完)

长按下面的二维码,即可订阅学院君最新发布的 PHP 入门到实战教程:

关于本系列教程的更多动态,请点击页面左下角的「阅读原文」链接查看。

php 7 class 初始化 销毁_在 PHP 中使用和管理 Session相关推荐

  1. python dict初始化大小_在Python中初始化/创建/填充Dict的Dict

    我必须在为我的研究编写代码时经常这样做.您将希望使用defaultdict包,因为它允许您添加键:值对在任何级别上,通过简单的分配.回答完你的问题我会给你看的.这是直接来源于我的一个程序.关注最后4行 ...

  2. python 初始化 元组_在Python中重新初始化元组

    python 初始化 元组 Python | 重新初始化元组 (Python | Reinitializing tuple) In this tutorial, we will learn how c ...

  3. 以下关于java中布局管理说法错误的是_对于 Java 中的布局管理器,以下说法中错误的是( )。_2019复习答案_学小易找答案...

    [单选题]下列哪个酶与丙酮酸生成糖无关? [单选题]宋代( )的产地是当时的福建建安. [单选题]建筑平面图中,外部尺寸一般标注( )尺寸. [单选题]MCS - 51 单片机的 CPU 主要的组成部 ...

  4. es6 依赖循环_探索 JavaScript 中的依赖管理及循环依赖

    我们通常会把项目中使用的第三方依赖写在 package.json 文件里,然后使用 npm .cnpm 或者 yarn 这些流行的依赖管理工具来帮我们管理这些依赖.但是它们是如何管理这些依赖的.它们之 ...

  5. mysql怎么做库存管理_电商中的库存管理实现-mysql与redis

    库存是电商系统的核心环节,如何做到不少卖,不超卖是库存关心的核心业务问题.业务量大时带来的问题是如何更快速的处理库存计算. 此处以最简模式来讨论库存设计. 以下内容只做分析,不能直接套用,欢迎各位同道 ...

  6. springmvc开启事务_在Controller中添加事务管理

    写这篇文章之前先说明一下: 1. Controller中添加事务管理,是可行的,但是强烈不推荐,因为不符合实际开发场景,还会导致一系列问题 2. 事务请在Service处理,所有的业务逻辑请写在 Se ...

  7. Spring注解开发-初始化/销毁方法注解

    初始化/销毁方法. 初始化:@PostConstruct相当于init-method="myInit" @PreDestory相当于是destroy-method="my ...

  8. java初始化数据报_初始化java原因

    虚拟机的类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类 即虚拟机的类加载机制. 在Java中,类型的加载.链接 ...

  9. vue 初始化方法_前端发展方向指南—Vue源码初始化

    Vue 的源码结构比较绕,同时使用了大量的面向对象的高级技巧.重写方法,扩展方法,多态等应用.从 Vue 实例的加载过程就可以看出来,这一节重点看看 Vue 的源码加载流程是什么. 前言 vue已是目 ...

最新文章

  1. android 按键kl文件,Android添加新按键
  2. 记录解决二次编码问题
  3. 如何通过 C# 比较两幅图片的相似度?
  4. TIOBE 6月排行:C# 以微弱的优势超过了 Visual Basic .NET 的排名,再次进入 TOP 5
  5. 车站信号计算机联锁系统英语,车站信号计算机联锁-复习题
  6. windows下mysql8.x配置远程连接
  7. 【iOS】UITabView/UICollectionView 全选问题
  8. 51Nod 1058 N的阶乘的长度
  9. 【转载】Android 工具-adb原理
  10. 解决在eclipse里没有“Dynamic Web Project“这个选项的问题
  11. 文本相似度的方法对比
  12. Java学生管理系统功能结构图
  13. 小程序中从后台获取内容纯数字、纯字母超出父盒子宽度时不换行 解决方法
  14. Reset 重置按钮
  15. 通过Python获取维基百科中概念词条的维基信息
  16. 世界自然基金会推出区块链工具以跟踪食品供应链
  17. 南京大学2021计算机考研复试线是多少,南京大学2021研究生复试分数线是多少
  18. 如何使用AE制作文字破碎动画?制作ae破碎文字特效教程分享
  19. leetcode 714. 买卖股票的最佳时机含手续费(java)
  20. ROS学习笔记 程序简单示例一:发布者与订阅者(talker和listener)

热门文章

  1. Jade/Pug模板引擎
  2. redis指定配置文件启动_redis基础知识整理-安装
  3. 电脑字体在哪个文件夹_【安卓】造字(下):如何将生成的字体设置为手机系统显示字体...
  4. mac下php的坑,MAC下安装laravel时遇到的坑
  5. 三星计算机用户的密码忘了,如果三星计算机忘记了开机密码怎么办
  6. python request和urllib_requests和urllib.request的区别是什么?
  7. 1_数据分析—数据载入、导出和探索
  8. 螺旋千斤顶设计大作业_新型飞机千斤顶的优化设计
  9. dubbo调用超时回滚_如何处理Dubbo调用超时?
  10. 关于码云的一些基本知识_一些关于 CPU 的基本知识