11_会话原理与实现流程

1、会话的基本知识

# 会话

## 1.会话是什么?

客户端与服务器之间的对话交流

## 2.为什么需要会话?

-http 协议是无状态的(六亲不认)
    -同一用户多次访问同一网站,对网站来说,每次都是全新的
    -网站不能识别用户身份,不能为用户提供个性化服务
-用户需要被关怀被尊重
    -相同的操作,不应该换个页面就重复进行,例如登录、注册
    -用户信息应该在多个页面间共享,例如购物车

## 3.会话的基本步骤

> 和人与人之间的交流几乎一样

1.开启会话:初次见面,相互介绍,递个名片,请多关照
2.访问网站:再次见面,报上姓名,原来是你,欢迎光临
3.数据交换:对话交流,及时反馈,谈话内容,立刻存档
4.销毁对话:相谈甚欢,恋恋不舍,谈判破裂,关门送客

## 4.会话存储位置

1.客户端:`cookie`
2.服务端:`session`

## 5.PHP对应的操作变量
1.`$_COOKIE`
2.`$_SESSION`

2、客户端会话

<?php
namespace _0822;

//客户端会话存储(cookie)

//1.设置(正常情况下,会把中文的值变为Unicode编码,如果想显示中文,就用setrawcookie)
//raw是原始的意思

// setcookie('site','php中文网');
setrawcookie('site','php中文网');

//2.查看($_COOKIE是一个超全局变量,无作用域,任何地方都能用)
echo $_COOKIE['site'] ?? '未定义site'. '<hr>';

//3.设置多个(建议使用数组语法)
setcookie('user[name]','admin');
setcookie('user[email]','admin@qq.com');
setcookie('user[age]',40);

if(isset($_COOKIE['user'])){
    foreach($_COOKIE['user'] as $key => $value){
        printf('[%s] => %s<br>',$key,$value);
    }
}else{
    echo '未定义user';
}

//4.删除(setcookie的第三个参数是过期时间)
//给一个已过期的时间就可以了
setcookie('welcome','hello world',time()-3600);

/**
 * 将过多信息存储在客户端,并不合适
 * 1.数量受限:30个
 * 2.空间受限:4k
 * 3.安全隐患:天生不可避免
 * 
 * 所以,会话信息推荐存储在服务器端
 * 客户端只需要保存一个会话id,用于标识访问身份即可
 */

3、服务端会话 

<?php

namespace _0822;

//服务器端会话(session)

//1.启动会话
session_start();

/**
 * 启动会话做了二件事
 * 1.浏览器:创建会话ID:PHPSESSID,一串md5加密的字符串
 * 2.服务器:创建与浏览器会话ID对应的会话文件,一个会话文件对应一个用户
 */

//1.设置
$_SESSION['email'] = 'admin@php.cn';
//sha1是40位字符串,md5是32位
$_SESSION['password'] = sha1(md5('123456') . 'phpcn123');

//session
//email|s:12:"admin@php.cn";password|s:40:"8dc7df199a6642d631c11de069b2357e4b470cd0";
//!email指变量名,s指字符串,12指它值的长度(admin@php.cn的长度)
//把用户的session信息进行了序列化,序列化就是把这些变量,数组,或对象转换为字符串形式,这样的话就方便存储到数据库中,继而便于通过网络进行传输,或者各个语言间的数据交换

//2.更新
$_SESSION['email'] = 'peter@php.cn';

//3.删除
// unset($_SESSION['email']);
// unset($_SESSION['password']);

//一个一个删除太low了,更优雅地删除(一次性删除全部的session信息)
session_unset();

//更狠地删除(直接把服务器的会话文件都删除了)
session_destroy();

 

比如说登录时,就带上登录信息,跳转到handler.php这个页面进行登录处理到这个数据表中进行验证,看看有没有这个用户,如果注册,就把用户插入到表中,退出就直接销毁会话就可以了. 

4、登录页面(login.php)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
</head>

<body>
    <h3>用户登录</h3>
    <form action="handle.php?action=login" method="post">
        <div>
            <label for="email">邮箱:</label>
            <input type="email" name="email" id="email" placeholder="demo@email.com" required autofocus>
        </div>

        <div>
            <label for="password">密码:</label>
            <input type="password" name="password" id="password" placeholder="不少于6位" required>
        </div>

        <div>
            <button>提交</button>
        </div>
    </form>
    <a href="register.php">还没有帐号, 注册一个吧</a>
</body>

</html>

 5、入口文件(index.php)

<?php
namespace _0822;
session_start();
//判断是否已经登录?
if(isset($_SESSION['user'])){
    $user = unserialize($_SESSION['user']);
}
// print_r($user);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页/入口文件</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
    <nav>
        <a href="index.php">我的博客</a>
        <?php if(isset($user)) :?>
            <span style="margin-left: 300px;"><?=$user['name']?></span>
            <a id="logout">退出</a>
        <?php else:?>
            <a href="login.php">登录</a>
        <?php endif?>
    </nav>

    <script>
        document.querySelector('#logout').addEventListener('click',function(event){
            if(confirm('是否退出')){
                //禁用默认行为,其实就是禁用原<a>标签的点击跳转行为,使用事件中的自定义方法去处理
                event.preventDefault();
                //跳转到退出事件处理器
                window.location.assign('handle.php?action=logout');
            }
        })
    </script>
</body>
</html>

6、 注册页面(register.php)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <title>注册用户</title>
</head>

<body>
    <h3>用户注册</h3>
    <form action="handle.php?action=register" method="post" onsubmit="return compare()">
        <div>
            <label for="name">呢称:</label>
            <input type="text" name="name" id="name" placeholder="不少于3个字符" required autofocus>
        </div>
        <div>
            <label for="email">邮箱:</label>
            <input type="email" name="email" id="email" placeholder="demo@email.com" required>
        </div>

        <div>
            <label for="p1">密码:</label>
            <input type="password" name="p1" id="p1" placeholder="不少于6位" required>
        </div>

        <div>
            <label for="p2">重复:</label>
            <input type="password" name="p2" id="p2" placeholder="必须与上面一致" required>
        </div>

        <div>
            <button>提交</button><span id="tips" style="color: red"></span>
        </div>
    </form>
    <a href="login.php">我有帐号,直接登录</a>

    <script>
        // 验证二次密码是否相等?
        function compare() {
            if (document.forms[0].p1.value.trim() !== document.forms[0].p2.value.trim()) {
                document.querySelector('#tips').innerText = '二次密码不相等';
                return false;
            }
        }
    </script>
</body>

</html>

7、处理器文件(handle.php)

<?php

namespace _0822;

use PDO;

//开启会话:必须写在第一行

session_start();

//sql

//查询用户表中的数据use表
$db = new PDO('mysql:dbname=phpedu', 'root', 'root');
$stmt = $db->prepare('SELECT * FROM `user`');
if($stmt->execute()){
    $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
}else{
    print_r($stmt->errorInfo());
}


//获取用户操作类型
$action  = strtolower($_GET['action']);

switch ($action) {
        //1.登录
    case 'login':
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            //获取登录用户的数据:邮箱和密码
            $email = $_POST['email'];
            $password = sha1($_POST['password']);
            // echo $password;
            // die($email);
            $result = array_filter($users, function ($user) use ($email, $password) {
                return $user['email'] === $email && $user['password'] === $password;
            });
            if (count($result) === 1) {
                //登陆成功,写入session
                $_SESSION['user'] = serialize(array_pop($result));
                exit('<script>alert("验证通过"); location.href="index.php";</script>');
            }
        }

        //2.退出
        //no break
    case 'logout':
        if (isset($_SESSION['user'])) {
            session_destroy();
            exit('<script>alert("退出成功");location.href="index.php"</script>');
        }
        //注册
    case 'register':

        //1.获取新用户数据
        $name = $_POST['name'];
        $email = $_POST['email'];
        $password = sha1($_POST['p2']);
        $register_time = time();

        //2.sql
        $sql = <<<SQL
            INSERT `user`
            SET `name` = ?,
                `email` = ?,
                `password` = ?,
                `register_time` = ?;   
        SQL;

        $stmt = $db->prepare($sql);
        $data = [$name, $email, $password, $register_time];
        if ($stmt->execute($data)) {
            if ($stmt->rowCount() > 0) {
                //注册成功之后,让用户自动登录
                $sql = 'SELECT * FROM `user` WHERE `id` = ' . $db->lastInsertId();

                $stmt = $db->prepare($sql);
                $stmt->execute();
                $newUser = $stmt->fetch(PDO::FETCH_ASSOC);
                $_SESSION['user'] = serialize($newUser);



                exit('<script>alert("注册成功");location.href="index.php"</script>');
            } else {
                exit('<script>alert("注册失败");location.href="register.php"</script>');
            }
        } else {
            print_r($stmt->errorInfo());
        }

        //no break
    default:
        exit('参数非法或未定义操作');
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七色的天空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值