XSS渗透 Session

一、为什么需要 Session?(Cookie 的两个问题)

Cookie 虽然解决了 HTTP 无状态的问题,但带来了新问题:

  1. 存储空间浪费:访问网站越多,浏览器本机保存的 Cookie 越多(每个网站可能下发几十个),占用磁盘/内存。
  2. 通信效率降低:每次请求都要携带所有 Cookie(可能几百字节甚至几 KB),增加 HTTP 传输开销,拖慢速度。
    核心思路 :将大量的键值对信息从客户端转移到服务端存储,客户端只保存一个唯一的标识(类似医院的"诊疗卡号")。

二、Session 是什么?

  • Session(会话):服务端为每个客户端开辟的一块存储空间,用于保存该客户端的键值对数据(如用户ID、登录状态、权限等)。
  • Session ID:服务端生成的一个唯一标识,通过 Cookie 下发给客户端。客户端后续请求只需携带这个 ID,服务端根据 ID 找到对应的 Session 数据。

    关键点:
  • Session 不是 替代 Cookie,而是基于 Cookie 工作
  • Cookie 中保存的内容被简化为一个 Session ID(如 PHPSESSID=abc123)。
  • 真正的用户数据保存在服务端(文件、内存、Redis 等)。

三、Session 的工作流程(四步)

|---------|----------|--------------------------------------------------------|------------------|
| 步骤 | 方向 | 动作 | 说明 |
| 1. 创建会话 | 客户端第一次访问 | 服务端调用 session_start() 生成 Session ID,通过 Set-Cookie 下发 | 此时 Session 存储区为空 |
| 2. 写入数据 | 服务端 | 往 _SESSION 中存入键值对(如 _SESSION['username']='admin' ) | 数据保存在服务端 |
| 3. 验证会话 | 客户端再次访问 | 浏览器自动携带 Cookie 中的 Session ID,服务端根据 ID 找到 Session 数据 | 判断是否已登录、有无权限 |
| 4. 销毁会话 | 用户注销 | 服务端清空 $_SESSION 并调用 session_destroy() ,同时删除相关持久 Cookie | 彻底结束会话 |


|---------------|-------------------------------|-------------------------------------------|
| 对比项 | Cookie | Session |
| 数据存储位置 | 客户端(浏览器) | 服务端(文件/内存/Redis) |
| 每次请求传输的内容 | 所有 Cookie 的 name=value(可能几十个) | 仅一个 Session ID(如 PHPSESSID=xxx ) |
| 存储大小限制 | 每个域名约 50 个,每个 4KB | 受服务端资源限制,可存大量数据 |
| 安全性 | 明文存储,可被篡改/查看(HttpOnly 可部分防御) | 数据不暴露给客户端,更安全 |
| 生命周期 | 可设置过期时间,也可会话级 | 通常随会话结束或主动销毁 |
| 依赖关系 | 独立存在 | 依赖 Cookie 传递 Session ID(也可通过 URL 重写,但不常用) |


五、Session 的存储位置(配置相关)

  • 默认(PHP):以文件形式保存在服务器磁盘上(如 /tmp 或 PHP 配置指定的目录)。每个 Session 对应一个文件,文件名包含 Session ID。 文件内容为序列化后的 $_SESSION 数据,例如:username|s:5:"admin";islogin|i:1;
  • 可配置存储方式
    • 文件(默认)
    • 内存缓存(如 Memcached)
    • 数据库(如 MySQL)
  • Redis(常用,支持分布式)
    示例:
    修改 PHP 配置 session.save_handler = redis 和 session.save_path = "tcp://127.0.0.1:6379" 可让 Session 存入 Redis。

六、Session 的典型应用场景

  1. 用户登录状态保持
  • 登录成功后,将 user_id 和 is_login 存入 $_SESSION。
  • 后续请求只需校验 Session 中是否有 is_login=true,无需重复查询数据库。
  1. 购物车数据
  • 未登录时购物车数据可存 Cookie,登录后合并到 Session 中。
  1. 验证码/短信验证码存储
  • 生成验证码时存入 Session,用户提交时对比,防止篡改。
  1. 权限控制
  • 用户登录后,将角色、权限列表存入 Session,避免每次请求都查数据库。

七、"记住我"(7天免登录)的实现方式

Session 本身默认过期时间较短(如 1440 秒)。要实现"7天内自动登录",需要额外设置持久 Cookie,并配合 Session 使用:

php 复制代码
// 登录时勾选"记住我"
if($_POST['remember']=="yes") {
    setcookie("admin", $username, time()+7*24*60*60);
    setcookie("code", md5($username.md5($password)), time()+7*24*60*60);
}
  • 真正登录凭证存在 _SESSION 中(_SESSION['username'] 和 $_SESSION['islogin'])。
  • 持久 Cookie(admin 和 code)用于下次访问时自动重建 Session。
  • 典型自动登录流程:用户再次访问时,先检查 Session 是否为空;若为空则校验持久 Cookie,校验通过后重新 session_start() 并写入 $_SESSION。

八、注销时如何完整清除会话

正确的注销代码应做四件事(参考 logout.php):

php 复制代码
session_start();                      // 1. 恢复当前会话
$username = $_SESSION['username'];   // 2. 记录用户名用于提示
$_SESSION = array();                 // 3. 清空 $_SESSION 数组
session_destroy();                   // 4. 删除服务端的 Session 文件
setcookie("admin",'',time()-1);      // 5. 删除"记住我"的持久 Cookie
setcookie("code",'',time()-1);       // 6. 同上

注意:

  • 这里没有删除 PHPSESSID 这个 Cookie(浏览器还会保留一个过期的 Session ID),但服务端 Session 已销毁,该 ID 无效。如需彻底删除客户端 Session ID,可执行

    php 复制代码
    setcookie(session_name(), '', time()-3600, '/')。
  • 持久 Cookie(如 admin、code)必须手动删除,否则下次访问时可能被错误地用于自动登录。


九、完整登录流程时序

|----------------|------------|------------------------------------|--------------------------------------------------------------|
| 步骤 | 文件 | 动作 | 关键代码 |
| 1. 用户访问登录页 | login.html | 显示表单,包含用户名、密码、"记住我"复选框 | 无 |
| 2. 提交表单 | login.php | session_start() 开启会话 | session_start(); |
| 3. 验证账号密码 | login.php | 硬编码验证 admin/123456 | if((username=='admin')\&\&(password=='123456')) |
| 4. 写入 Session | login.php | 保存用户名和登录状态 | _SESSION\['username'\]=username; _SESSION\['islogin'\]=1; | | 5. 设置持久 Cookie | login.php | 如果勾选"记住我",设置 7 天有效 Cookie | setcookie("admin",username,time()+7*24*60*60); |
| 6. 跳转用户中心 | login.php | header('refresh:3;url=index.php'); | |
| 7. 验证登录状态 | index.php | 检查 _SESSION\['username'\] 是否存在 | if(isset(_SESSION['username'])) |
| 8. 显示个人中心 | index.php | 显示欢迎信息和注销链接 | echo $_SESSION['username'].":你好..."; |
| 9. 注销 | logout.php | 清除 Session 和持久 Cookie | session_destroy(); setcookie("admin",'',time()-1); |


十、注意事项

  • session_start() 必须在任何输出之前调用(包括 header() 和 echo),否则会报错。
  • 不同浏览器的 Session 互不影响,因为 Cookie 不共享。同一浏览器的不同标签页/窗口共享 Session。
  • 分布式环境需将 Session 集中存储(如 Redis),不能使用默认的文件存储。
  • Session 不是万能的:对于纯 API 服务(无浏览器环境),更多使用 Token(如 JWT)。

十一、一句话总结

Cookie 存在客户端,用来保存数据(如 Session ID)。
Session 存在服务端,用来保存真正的用户数据。
两者配合:服务端通过 Cookie 下发一个 Session ID,客户端下次请求带上它,服务端就能找到对应的 Session 数据。


这份笔记已经包含了原版的所有内容,并融入了你提供的代码示例和补充说明。如果你觉得还有需要微调的地方(比如去掉某些细节或增加流程图文字),请告诉我。
下面附上参考代码
login.php

php 复制代码
<?php 
 header("Content-Type:text/html;charset=utf-8"); 
 // 开启会话,产生sessionid
 session_start(); 
 if(isset($_POST['login'])) 
 { 
  $username = trim($_POST['username']); 
  $password = trim($_POST['password']); 
  if(($username=='')||($password=='')) 
  { 
   header('refresh:3;url=login.html'); 
   echo "用户名或密码不能为空,3秒后跳转到登录页面"; 
   exit; 
  } 
  // 用户名和密码没有查表,直接写死,只是个参考
  else if(($username!='admin')||($password!='123456')) 
  { 
   //用户名或密码错误 
   header('refresh:3;url=login.html'); 
   echo "用户名或密码错误,3秒后跳转到登录页面"; 
   exit; 
  } 
  // 没有查表,直接写死
  else if(($username=='admin')&&($password=='123456')) 
  { 
   //登录成功将信息保存到session中 
   $_SESSION['username']=$username; 
   $_SESSION['islogin']=1; 
   //如果勾选7天内自动保存,则将其保存到cookie 
   if($_POST['remember']=="yes") 
   { 
    setcookie("admin",$username,time()+7*24*60*60); 
    setcookie("code",md5($username.md5($password)),time()+7*24*60*60); 
   } 
   else 
   { 
    setcookie("admin",'',time()-1); 
    setcookie("code",'',time()-1); 
   } 
   //跳转到用户首页 
   header('refresh:3;url=index.php'); 
  } 
 } 
?>

index.php

php 复制代码
<?php 
 header("Content-Type:text/html;charset=utf-8"); 
 session_start(); 
 // session中有这个用户名,代表已经登录
 if(isset($_SESSION['username'])) 
 { 
  echo $_SESSION['username'].":你好,欢迎进入个人中心!<br/>"; 
  echo "<a href='logout.php'>注销</a>"; 
 } else { 
  // 没有这个用户名的session值
  echo "你还未登录,请<a href='login.html'>登录</a>"; 
 } 
?> 

logout.php

php 复制代码
<?php 
 header("Content-Type:text/html;charset=utf-8"); 
 session_start(); 
 //清除session 
 $username=$_SESSION['username']; 
 $_SESSION=array(); 
 session_destroy(); 
 //清除cookie 
 setcookie("username",'',time()-1); 
 setcookie("code",'',time()-1); 
 echo "拜拜, $username, 欢迎下次光临"; 
 echo "重新<a href='login.html'>登录</a>"; 
?> 
相关推荐
你觉得脆皮鸡好吃吗19 小时前
XSS渗透 COOKIE
网络·http·okhttp·网络安全学习
JiaWen技术圈19 小时前
React 19 Fiber 架构 深度解析
前端·react.js·架构
大阳光男孩19 小时前
【UniApp小程序开发】解决无法使用Vue自定义指令的完美替代方案:权限组件封装
前端·vue.js·uni-app
wWYy.19 小时前
WebSocket
网络·websocket·网络协议
只要微微辣19 小时前
Uniapp 微信小程序 Canvas画框标注:拖拽缩放全攻略
前端·微信小程序·uni-app·canvas·canva可画
念何架构之路19 小时前
DNS和HTTP DNS
网络·网络协议·http
希冀12319 小时前
【CSS学习第十三篇】
前端·css·学习
踏歌~19 小时前
个人简历网站搭建:2 解析原有结构并构建首页
前端
Moment19 小时前
面试官:上下文过长导致语义偏移,工程上怎么优化
前端·后端·面试
kkoral19 小时前
Vue3 图片标框功能实现方案
前端·vue.js·vscode·typescript