news 2026/10/10 12:20:12

Day23 XD安全学习笔记-PHP 应用后台模块SessionCookieToken身份验证唯一性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day23 XD安全学习笔记-PHP 应用后台模块SessionCookieToken身份验证唯一性

目录

一.Cookie

1.原理

2.代码实现

(1)admin-c.php

(2)Index-c.php

(3)logout-c.php

3.交作业

二.Session

1.原理

2.代码实现

(1)admin-s.php

(2)index-s.php

(3)logout-s.php

3.交作业

三.token

1.原理

3.代码实现

(1)token.php

(2)Token_check

3.作业

​编辑


在前一天的基础上实现后台登录cookie、session和token的身份验证。表单是让deepseek生成的简单页面。

B站免费课程链接:

www.bilibili.com/video/BV12om2YTEgW/?spm_id_from=333.788.videopod.episodes&vd_source=7d8464f1ea919ffdc1761c211c6d1c4e&p=24

一.Cookie

1.原理

想象浏览器是一个每天都要去“网站大厦”办事的访客,服务器就是大厦前台。第一次你来的时候,报上账号密码,前台核对无误后,不会把你的身份证复印件贴在你脸上,而是递给你一张写着随机编号的寄存牌——这张寄存牌就是 Cookie。浏览器会乖乖把它收进口袋。以后你每次再去这栋大厦,还没等你开口,浏览器就自动把寄存牌掏出来递给前台:“喏,这是我的牌。”前台拿着编号去后台柜子里一查,就知道你是几号会员、有没有过期、是不是已经退房。牌子上没有你的密码,只有一串谁也猜不到的编号;就算你偷偷把编号改了,后台查不到对应记录,照样不认你。退出登录时,前台要么把这张牌作废,要么让浏览器直接把牌扔掉。

所以,Cookie 的工作机制就像一张“会自动出示的临时通行证”:服务器发牌,浏览器存牌,每次访问同一网站时自动亮牌,服务器凭牌去后台核对身份,再决定放不放行。

Cookie是保存在浏览器,只要访问的cookie正确就能通过校验。常常会有钓鱼来做cookie劫持,点击不知名链接就自动访问敏感站点,然后把站点的cookie发给黑客。从而达到用受害者身份登录网站进行非法操作的目的。

2.代码实现

分为登录页面admin-c.php,登录成功后的后台页面index-c.php和退出登录logout-c.php。

(1)admin-c.php
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>后台登录</title> <style> * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; background: #f0f2f5; font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif; } .login-box { /* 关键:脱离文档流,相对视口居中 */ position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 100%; max-width: 360px; padding: 32px 28px; background: #fff; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, .08); } .login-box h1 { margin: 0 0 24px; font-size: 20px; text-align: center; color: #333; } .form-item { margin-bottom: 18px; } .form-item label { display: block; margin-bottom: 6px; font-size: 14px; color: #555; } .form-item input { width: 100%; height: 40px; padding: 0 12px; font-size: 14px; border: 1px solid #dcdfe6; border-radius: 6px; outline: none; transition: border-color .2s; } .form-item input:focus { border-color: #409eff; } .btn { width: 100%; height: 42px; margin-top: 8px; font-size: 15px; color: #fff; background: #409eff; border: none; border-radius: 6px; cursor: pointer; transition: background .2s; } .btn:hover { background: #66b1ff; } </style> </head> <body> <div class="login-box"> <h1>后台管理系统</h1> <!-- 表单:POST 提交 --> <form action="" method="post" autocomplete="off"> <div class="form-item"> <label for="username">账号</label> <input type="text" id="username" name="username" placeholder="请输入账号" required> </div> <div class="form-item"> <label for="password">密码</label> <input type="password" id="password" name="password" placeholder="请输入密码" required> </div> <button type="submit" class="btn">登 录</button> </form> </div> </body> </html> <?php include '../config.php'; //登录文件 /* cookie验证流程 1、接收输入的账号密码 2、判断账号密码正确性 3、正确后生成的cookie进行保存 3.1错误的账号密码进行提示 4、跳转至成功登录的页面 */ //1、接收输入的账号密码 $user=$_POST['username']; $pass=$_POST['password']; //2、判断账号密码正确性 //连接数据库 进行数据库查询将数据进行对比 $sql="select * from admin where username='$user' and password='$pass';"; $data=mysqli_query($con,$sql); //查询数据传给变量$data if($_SERVER["REQUEST_METHOD"]=="POST"){ if(mysqli_num_rows($data)>0){ //mysqli_num_row函数是用来读取数据集有多少行,如果通过sql语句在数据库查询到有这个用户和相应的密码记录,那数据集就不会为0。则判断用户登录成功,继续往下执行。 $expire = time() + 60 * 60 * 24 * 30; // 单位为秒,一个月后过期 setcookie('username', $user, $expire, '/');//把用户名写入cookie setcookie('password', $pass, $expire, '/');//把密码写入cookie echo '<script>alert("登录成功!")</script>'; header('Location: index-c.php');//跳转到index-c.php的页面,也就是登录成功的页面 exit(); }else{ //判断用户登录失败 echo '<script>alert("登录失败!")</script>'; } }
(2)Index-c.php
<!--cookie校验,防止没有登陆直接未授权访问该页面--> <?php if($_COOKIE['username']!='admin' and $_COOKIE['password']!='123456'){ //获取cookie中的'username'和'password'字段是否不等于'admin'和'123456',不等于则继续往下执行 header('Location: admin-c.php'); //跳转到登陆页面进行身份校验。 } ?> //登录首页页面 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>后台首页</title> </head> <body> <h1>后台首页</h1> <p>欢迎您,<?php echo $_COOKIE['username']; ?>!</p> <p><a href="logout-c.php">退出登录</a></p> </body> </html>
(3)logout-c.php
<?php setcookie('username', '', time() - 3600, '/');//setcookie的第三个参数是过期时间,当前时间减去3600已经是过期了,减去1也可以,都是已经过去时间失效了。 setcookie('password', '', time() - 3600, '/'); // 跳转到登录页面 header('Location: admin-c.php'); exit; ?>

3.交作业

登录页面

后台首页

浏览器中存储的cookie内容:

二.Session

1.原理

把服务器想象成一座管理严格的游乐园,登录页 admin-s.php 就是大门口。你递上账号密码,验票员去数据库名单里核对;一旦确认,他并不让你把身份证贴在脑门上到处跑,而是给你手腕套一个独一无二的手环——这就是 Session ID,浏览器通常把它存在 Cookie 里。与此同时,游乐园后台的档案柜里多了一份你的临时档案:你是谁、是不是 admin、密码对不对、能进哪些地方,这些就是 $_SESSION。之后你每走到一个页面,比如 index-s.php,门口保安不看你别的东西,只看手环编号,然后回档案柜里一查:编号有没有、档案在不在、身份对不对。对上了,放行;对不上、手环过期、档案被销毁,或者你从 logout-s.php 出口剪掉手环,就一律被请回大门口重新登录。所以 Session 验证的精髓是:客户端拿的只是一张“临时通行证编号”,真正说了算的身份档案,始终锁在服务器自己手里。

因为真正的凭据内容在服务器端,不像cookie直接放在浏览器,所以比前面的cookie安全一点,存储到服务器,但是增加服务器存储session的成本。

流程图

总体架构图

登录、校验、退出时序图

2.代码实现

(1)admin-s.php
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>后台登录</title> <style> * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; background: #f0f2f5; font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif; } .login-box { /* 关键:脱离文档流,相对视口居中 */ position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 100%; max-width: 360px; padding: 32px 28px; background: #fff; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, .08); } .login-box h1 { margin: 0 0 24px; font-size: 20px; text-align: center; color: #333; } .form-item { margin-bottom: 18px; } .form-item label { display: block; margin-bottom: 6px; font-size: 14px; color: #555; } .form-item input { width: 100%; height: 40px; padding: 0 12px; font-size: 14px; border: 1px solid #dcdfe6; border-radius: 6px; outline: none; transition: border-color .2s; } .form-item input:focus { border-color: #409eff; } .btn { width: 100%; height: 42px; margin-top: 8px; font-size: 15px; color: #fff; background: #409eff; border: none; border-radius: 6px; cursor: pointer; transition: background .2s; } .btn:hover { background: #66b1ff; } </style> </head> <body> <div class="login-box"> <h1>后台管理系统</h1> <!-- 表单:POST 提交 --> <form action="" method="post" autocomplete="off"> <div class="form-item"> <label for="username">账号</label> <input type="text" id="username" name="username" placeholder="请输入账号" required> </div> <div class="form-item"> <label for="password">密码</label> <input type="password" id="password" name="password" placeholder="请输入密码" required> </div> <button type="submit" class="btn">登 录</button> </form> </div> </body> </html> <?php //登录文件-采用session验证 include '../config.php'; //1、接收输入的账号密码 $user=$_POST['username']; $pass=$_POST['password']; $sql="select * from admin where username='$user' and password='$pass';"; $data=mysqli_query($con,$sql); if($_SERVER["REQUEST_METHOD"]=="POST"){ if(mysqli_num_rows($data)>0){ session_start();//开启session会话 $_SESSION['username']=$user; $_SESSION['password']=$pass; header('Location: index-s.php'); exit(); }else{ echo '<script>alert("登录失败!")</script>'; }

}

(2)index-s.php
<?php //判断省去了数据库查询获取账号密码的操作 直接赋值 session_start(); if($_SESSION['username']!='admin' || $_SESSION['password']!='123456'){ //同前面的cookie header('Location: admin-s.php'); } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>后台首页</title> </head> <body> <h1>后台首页</h1> <p>欢迎您,<?php echo $_SESSION['username']; ?>!</p> <p><a href="logout-s.php">退出登录</a></p> </body> </html>
(3)logout-s.php
<?php // 开始会话 session_start(); // 清除 SESSION 变量,并销毁会话 session_unset(); session_destroy(); // 重定向到登录页面 header('Location: admin-s.php'); exit; ?>

3.交作业

页面是和cookie一样的,不过服务器多了session文件,PHP study的session文件默认存放位置:phpstudy_pro\phpstudy_pro\Extensions\tmp\tmp

这个位置还可以通过修改配置文件来改变:

phpstudy_pro\phpstudy_pro\Extensions\php\php7.3.4nts\php.ini

在这个文件中搜索session_save_path

session文件里面就是用户和账号密码

浏览器只存了编号

三.token

1.原理

用来唯一标识数据包。你可以把 Token 想象成服务器在用户打开登录页时,悄悄生成并塞进表单里的一张“一次性暗号纸条”,同时服务器自己把这张纸条的底根锁进 Session 保险柜里;当用户填写账号密码点击登录时,表单就会把这张“暗号纸条”一起交回服务器,服务器先看保险柜里有没有底根、有没有过期,再拿出底根和用户交回的纸条用 hash_equals() 仔细核对,只有完全一致且账号密码正确才放行;登录成功后,这张纸条立刻作废销毁,并重新生成 Session ID,就像一次性手环用完即撕,这样即使有人偷看、伪造 Cookie 或想重复提交旧请求,也因为没有服务器保险柜里的底根而无法蒙混过关。

运行机制

3.代码实现

(1)token.php
<?php //生成Token并且将其存储在Session中 session_start(); $token= bin2hex(random_bytes(16)); //将token保存到session中 $_SESSION['token']=$token; $_SESSION['token_time'] = time(); ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>后台登录</title> <style> * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; background: #f0f2f5; font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif; } .login-box { /* 关键:脱离文档流,相对视口居中 */ position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 100%; max-width: 360px; padding: 32px 28px; background: #fff; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, .08); } .login-box h1 { margin: 0 0 24px; font-size: 20px; text-align: center; color: #333; } .form-item { margin-bottom: 18px; } .form-item label { display: block; margin-bottom: 6px; font-size: 14px; color: #555; } .form-item input { width: 100%; height: 40px; padding: 0 12px; font-size: 14px; border: 1px solid #dcdfe6; border-radius: 6px; outline: none; transition: border-color .2s; } .form-item input:focus { border-color: #409eff; } .btn { width: 100%; height: 42px; margin-top: 8px; font-size: 15px; color: #fff; background: #409eff; border: none; border-radius: 6px; cursor: pointer; transition: background .2s; } .btn:hover { background: #66b1ff; } </style> </head> <body> <div class="login-box"> <h1>后台管理系统</h1> <!-- 表单:POST 提交 --> <form action="token_check.php" method="post" autocomplete="off"> <div class="form-item"> <input type="hidden" name="token" value="<?php echo $token;?>"> <label for="username">账号</label> <input type="text" id="username" name="username" placeholder="请输入账号" required> </div> <div class="form-item"> <label for="password">密码</label> <input type="password" id="password" name="password" placeholder="请输入密码" required> </div> <button type="submit" class="btn">登 录</button> </form> </div> </body> </html>
(2)Token_check
<?php session_start(); if ($_SERVER['REQUEST_METHOD'] !== 'POST') { exit('非法请求'); } //强制通过post方法提交 $username = $_POST['username'] ?? '';//从 POST 请求中取出 username 参数;如果这个参数不存在,就赋值为空字符串 '' $password = $_POST['password'] ?? ''; $postToken = $_POST['token'] ?? ''; // 1. 检查 session token 是否存在 if (!isset($_SESSION['token'], $_SESSION['token_time'])) { exit('登录失败:token 不存在'); } // 2. 检查 token 是否过期,例如 5 分钟 if (time() - $_SESSION['token_time'] > 300) { unset($_SESSION['token'], $_SESSION['token_time']); exit('登录失败:token 已过期'); } // 3. 比较 POST token 和 SESSION token if (!hash_equals((string)$_SESSION['token'], (string)$postToken)) { exit('登录失败:token 无效'); } // 4. 验证账号密码,实际项目应查数据库并用 password_verify if ($username === 'admin' && $password === '123456') { // token 一次性使用,防止重放 unset($_SESSION['token'], $_SESSION['token_time']); // 防止会话固定 session_regenerate_id(true); echo '登录成功!'; } else { echo '登录失败!'; }

3.作业

再次提交表单提示token不存在

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 12:19:25

2026通关榜!好用的降AIGC网站全盘点,效率直接拉满!

2026 年 AI 论文写作工具的综合王者是 千笔AI&#xff0c;国内毕业全流程首选千笔AI&#xff1b;千笔以中文润色 降重双能与全流程闭环见长&#xff0c;深度适配高校规范与查重系统&#xff0c;AI 率控制行业领先。按需求选对工具&#xff0c;论文效率可提升70%-90%&#xff0…

作者头像 李华
网站建设 2026/10/10 12:13:37

IPEmotion 曲线平滑计算:精准去除测试数据中的突起噪声

在实际车辆测试或其它实验室测试中&#xff0c;可能存在外界干扰&#xff0c;例如&#xff1a;工作环境温度发生突变&#xff0c;从而引起设备或系统内部元件参数发生了短暂的改变&#xff1b;外部使用了大功率设备产生了强磁场&#xff0c;从而干扰了测试系统等。特别当采样频…

作者头像 李华
网站建设 2026/10/10 12:12:07

Codeforces入门需要多少英语词汇

Codeforces入门阶段&#xff08;700-1000分&#xff09;&#xff0c;四年级零基础孩子只需要掌握100个以内的核心高频词汇&#xff0c;就能轻松读懂所有入门题面&#xff0c;完全不用额外背海量英语单词&#xff0c;和校内四年级英语学习进度高度适配。 &#x1f522; 核心词汇…

作者头像 李华
网站建设 2026/10/10 12:09:31

Python基础练习:注释与标识符的规范与避坑指南

我见过太多初学者学Python&#xff0c;第一个星期就开始啃列表、字典、函数&#xff0c;结果一写项目就乱套&#xff1a;变量名叫a、b、c&#xff0c;代码里一句注释都没有&#xff0c;过两周自己都看不懂自己写的什么。最后跑回来问我怎么回事&#xff0c;其实根子不在"知…

作者头像 李华
网站建设 2026/10/10 12:06:36

从x²=2到伽罗瓦群:域扩张、极小多项式与正规扩张完全梳理

如果你正在学抽象代数&#xff0c;或者备战考研&#xff0c;一定绕不开一个问题&#xff1a;方程 x2 在有理数世界里无解。教材上会写“引入 Q(√2)”&#xff0c;但很少有人把这一步背后的逻辑讲透。有理数域上的扩域&#xff0c;就是把 Q 不包含的数&#xff0c;通过某种受控…

作者头像 李华