如何让你的会话更安全,浅析Session与Cookie

        在我们面试的时候,面试官问及 XSS 漏洞的时候,我们常常会说比如劫持 Cookie,问及防御方法的时候,又常常会说设置httponly,本篇文章将从代码层面简单的普及 Session 和 Cookie 的生成过程,及防御的方法,希望看到这篇文章后,下一次遇到面试官的时候,你能够自豪的跟他说我知道防御 XSS 漏洞,能够把流程讲清楚,把原理讲明白!

先从 Cookie 讲起

        什么是 Cookie 呢?简单来说,当用户访问某个网站时,该网站的服务器会生成一个Cookie并发送到用户的浏览器,浏览器将其存储在本地计算机上。之后,每当用户再次访问该网站时,浏览器会将Cookie发送回服务器,服务器通过这些信息来识别用户,维持用户的登录状态,或者记录用户的浏览习惯、购物车。

        在 PHP 中,我们常常使用setcookie函数生成用户的 cookie,其函数解释如下:

  setcookie() 是 PHP 中的一个函数,用于设置 cookie 的各种属性,并向客户端发送 cookie。cookie 是一种机制,允许服务器向浏览器发送少量数据,并且浏览器会存储这些数据,下次访问同一网站时会发送回服务器。
函数的基本语法如下:

setcookie(name, value, expires, path, domain, secure, httponly);

参数说明:

  • name:cookie 的名称。
  • value:cookie 的值。
  • expires:cookie 过期的 Unix 时间戳。如果未设置或设置为 0,则 cookie 在浏览器会话结束时过期。
  • path:cookie 在哪个路径下有效。默认为当前脚本的目录以及所有子目录。
  • domain:cookie 在哪个域名下有效。注意,如果设置此参数,cookie 只会在指定的域下工作。
  • secure:如果设置为 true,cookie 只有在 HTTPS 连接下才会被发送。
  • httponly:如果设置为 true,cookie 将不会通过客户端脚本访问(如 JavaScript),有助于减少跨站脚本攻击(XSS)。

使用实例如下:

setcookie("user", "JohnDoe", time() + 3600, "/", "example.com", true, true);

        上面的代码会设置一个名为 user 的 cookie,值为 JohnDoe,有效期为 1 小时,在整个网站的路径下有效,仅适用于 example.com 域,并且需要通过安全的 HTTPS 连接传输,同时禁止通过客户端脚本访问。

为什么会有 Session

        众所周知,Session相对于Cookie来说,由于其服务器端存储的特性,通常被认为更安全。其安全性体现在与,Session数据存储在服务器上,这意味着它们不受浏览器设置的影响,并且不容易受到XSS攻击。同时,Session可以在用户会话期间持续存在,而不需要每次页面加载时都重新发送Cookie。

        在 PHP 中,我们常常使用session_start()函数来开始或继续一个现有的会话,用session_regenerate_id()防止会话劫持。

Session 与 Cookie 的区别如下:

Cookie

Session

存储位置

Cookie存储在用户的浏览器中,

Session数据存储在服务器上,这意味着它们不受浏览器设置的影响

安全性

如果Cookie没有设置为HttpOnly,那么JavaScript可以读取Cookie

Session通常通过一个会话ID来识别,这个ID在每次请求时都会发送到客户端。如果会话ID被窃取,攻击者可以使用它来访问用户的会话。

持久性

Cookie在每次HTTP请求和响应中都会被发送

Session可以在用户会话期间持续存在,而不需要每次页面加载时都重新发送Cookie。

跨域问题

由于同源策略(SOP),Cookie通常受到同源限制

Session不受SOP的限制,可以在不同域间使用。

01- 前端代码编写

        创建文件/session/index.html,用以提交用户名及密码,发送数据给到后端验证,实验代码如下:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>登录示例</title>
</head>
<body>
<form action="login.php" method="post">
    用户名:<input type="text" name="username" required>
    密码:<input type="password" name="password" required>
    <input type="submit" value="登录">
</form>
</body>
</html>

        前端页面反馈如下,麻雀虽小,五脏俱全:

02-后端 Session 生成

        创建后端处理 php 代码login.php,用以在通过验证的用户名和密码后,创建 Session 会话 ID,实验代码如下:

<?php
// 模拟用户数据库
$users = array(
    'user1' => 'password1',
    'user2' => 'password2'
);

// 从表单中获取用户名和密码
$username =$_POST['username'];
$password =$_POST['password'];

// 验证用户名和密码
if (isset($users[$username]) && $users[$username] === $password) {
    // 生成安全的会话ID
    session_start();
    session_regenerate_id();
    $_SESSION['loggedin'] = true;
    $_SESSION['username'] =$username;

    // 设置 session ID 到 Cookie
    setcookie(session_name(), session_id(), time() + 3600, '/', '', true, true);

    echo '<pre style="color: green; font-size: 18px;">';
    echo '登录成功,您的会话信息如下:';
    echo '<br><code>' . htmlspecialchars($_COOKIE[session_name()]) . '</code>';
    echo '</pre>';
} else {
    echo '<pre style="color: red; font-size: 18px;">';
    echo '登录失败,用户名或密码错误。';
    echo '</pre>';
}
?>

03-Session 会话使用

        在我们后端login.php生成完 Session 会话后,我们访问目标网站下的其他页面,比如info.php,需要通过 Session 去验证我们的身份,其后端代码如下:

<?php
// 检查会话是否已启动
if (!isset($_COOKIE[session_name()])) {
    // 如果会话未启动,重定向到登录页面
    header('Location: login.php');
    exit;
}

// 开始会话
session_start();

// 检查用户是否已登录
if (!isset($_SESSION['loggedin']) || !$_SESSION['loggedin']) {
    // 如果用户未登录,重定向到登录页面
    header('Location: login.php');
    exit;
}

// 显示用户信息
echo '<pre style="color: green; font-size: 18px;">';
echo '欢迎,' . htmlspecialchars($_SESSION['username']) . '!';
echo '</pre>';

?>

04-实验会话使用

        首先我们通过表单数据,构造 POST 型请求,将用户名user1和密码password1以 POST 型提交,服务器端返回数据包如下:

        此时当后端验证完成后,会发出set-cookie的命令,将sessionID进行设置后发送给前端浏览器。

        如果我们发送多次请求,会发现每次进行登录的请求时,都会重新设置sessionID,此时我们有多个sessionID,都是指向用户user1

        经过测试,这些sessionid都是指向用户user1,因此会发现这种重复性的登陆行为,并没有保障用户数据的安全性。

        旧的sessionid并未销毁,仍旧可被识别:

        这是因为我们在设置的过程中,并没有使用的相应识别机制,在重复提交登录表单的时候进行旧的 ID 的销毁,但是由于sessionID的爆破难度较高,因此安全性并不会受到较大的影响。

如何设置 httponly 来保证sessionID的安全性:

        在之前的后端代码中,有这样一行内容:

    // 设置 session ID 到 Cookie
    setcookie(session_name(), session_id(), time() + 3600, '/', '', true, true);

        最后两个参数true,保证了首先数据包只有在https下才能传送,保障了cookie不会被恶意的监听到,比如在防御中间人攻击上起到了一定的保护作用,其次第二个true,设置了httponly这样即使网站出现了 XSS 漏洞,也能保障我们的cookie不被黑客窃取,两者结合保障了会话的安全性。

总结

        在本篇文章中,我们首先从cookie讲起,理解了sessioncookie的不同,session为什么比cookie安全,以及如何去设置http-only及其设置的效果,希望对大家理解cookiesession有所帮助。

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值