1. 会话控制
- HTTP 是基于无连接的网络协议, 每一次访问, 对于服务器来说, 都是全新的
- 如果记住访问者,以及记录连接状态, 可以提升用户体验,完成许多个性化的功能
- 例如, 用户登录, 购物车等
- 其实让服务器记住用户的方式很简单, 就和生活中, 我们办会员卡是一样的
- 会员卡的存储位置有二个地方, 要么放在你身上, 要么保存到商家电脑中
- 所以, 网络中的用户资料也会保存在二个地方: 浏览器(客户端)和服务器中
- 保存到浏览器中的叫:
cookie
- 保存到服务器中的叫:
session
2. COOKIE
- 保存在客户端
- 变量:
$_COOKIE
- 变量过滤器:
filter_input(INPUT_COOKIE, key)
- 设置使用专用函数:
setcookie(名称, 值, 过期时间)
- 生效需要分二步完成: 先下达指令到浏览器, 再由浏览器完成 cookie 写入
3. SESSION
- 保存在服务器端
- 变量:
$_SESSION
- 变量过滤器:
filter_input(INPUT_SESSION, key)
- 设置使用专用函数:
setcookie(名称, 值, 过期时间)
- 生效需要分二步完成: 先下达指令到浏览器, 再由浏览器完成 cookie 写入
示例演示
<?php
session_start();
// cookie
// 设置: 由服务器设置到浏览器, 理解成商城给用户发了一个会员卡
setcookie('username', 'perter-zhu', time()+60, '/');
// 查询
echo $_COOKIE['username'];
// 更新
$_COOKIE['username'] = 'admin';
setcookie('username', 'admin', time()+60, '/');
echo $_COOKIE['username'];
// 删除
setcookie('username', null, time()-60, '/');
echo $_SESSION['email'];
--------------------------------------------
// session: 会话, 将客户端信息保存到服务器上
// 向用户发会员卡, 启动一个会话
session_start();
// 1. 给浏览器发一个id用来标识用户:session_id(), PHPSESSID
// 2. 在服务器上指定位置保存与用户id对应的用户信息
// sess_ku7neaha636g69t4mq0atj6d2i
// ku7neaha636g69t4mq0atj6d2i
$_SESSION['email'] ='admin@php.cn';
$_SESSION['password'] = sha1(md5('1234567'). 'php.cn123');
$_SESSION['email'] ='peter@php.cn';
session_destroy();
setcookie('PHPSESSID', '', time()-123456);
Cookie方式的用户登陆
index.php
// 判断是否已经登录?
if (isset($_COOKIE['user'])) $user = unserialize($_COOKIE['user']);
?>
<!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/index.css">
<title>首页</title>
</head>
<body>
<nav>
<a href="index.php">我的论坛</a>
<?php if (isset($user)) : ?>
<a href="" id="logout"><span style="color:red"><?php echo $user['name']?></span> 退出</a>
<?php else: ?>
<a href="login.php">登录</a>
<?php endif ?>
</nav>
</body>
<script>
// 为退出按钮创建事件监听器
document.querySelector('#logout').addEventListener('click', function(event) {
if (confirm('是否退出')) {
// 禁用默认行为, 其实就是禁用原<a>标签的点击跳转行为,使用事件中的自定义方法处理
event.preventDefault();
// 跳转到退出事件处理器
window.location.assign('handle.php?action=logout');
}
});
</script>
</html>
login.php
<?php
// 判断是否已登录
if (isset($_COOKIE['user']))
exit('<script>alert("请不要重复登录");location.href="index.php";</script>');
?>
<!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=login" method="post">
<div>
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" placeholder="demo@email.com" require 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>
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>
handle.php
<?php
// 查询用户表中的数据
$pdo = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root');
$stmt = $pdo->prepare('SELECT * FROM `users`');
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 处理用户登录与注册
$action = $_GET['action'];
switch ( strtolower($action)) {
// 登录
case 'login':
// 判断请求是否合t法
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 获取需要验证的数据
$email = $_POST['email'];
$password = sha1($_POST['password']);
$results = array_filter($users, function($user) use ($email, $password) {
return $user['email'] === $email && $user['password'] === $password;
});
if (count($results) === 1) {
setcookie('user', serialize(array_pop($results)));
exit('<script>alert("验证通过");location.href="index.php"</script>');
} else {
exit('<script>alert("邮箱或密码错误,或者还没有帐号");location.href="login.php";</script>');
}
} else {
die('请求类型错误');
}
break;
// 退出
case 'logout':
if (isset($_COOKIE['user'])) {
setcookie('user', null , time()-3600);
exit('<script>alert("退出成功");location.assign("index.php")</script>');
}
break;
// 注册
case 'register':
// 1. 获取到所有新用户数据
$name = $_POST['name'];
$email = $_POST['email'];
$password = sha1($_POST['p1']);
$register_time = time();
// 2. 将新用户插入到表中
$sql = "INSERT `users` SET `name`='{$name}', `email`='{$email}', `password`='{$password}', `register_time`={$register_time}";
$stmt = $pdo->prepare($sql);
$stmt->execute();
if ($stmt->rowCount() === 1) exit('<script>alert("注册成功");location.assign("login.php")</script>');
else exit('<script>alert("注册失败");location.assign("login.php")</script>');
break;
// 未定义
default:
exit('未定义操作');
}
index.css
nav {
height: 40px;
background-color: deepskyblue;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
nav > a {
color: white;
text-decoration: none;
}
style.css
body {
display: flex;
flex-direction: column;
text-align: center;
color: #555;
font-weight: 300;
}
body h3 {
font-weight: 300;
font-size: 20px;
margin-bottom: 10px;
}
body form {
width: 220px;
padding: 20px;
box-sizing: border-box;
background-color: skyblue;
margin: auto;
border-radius: 5px;
box-shadow: 0 0 5px #aaa;
}
body form > div {
height: 36px;
display: flex;
justify-content: space-between;
align-items: center;
}
body form div:last-of-type {
display: flex;
justify-content: center;
}
body form input {
border: none;
outline: none;
padding-left: 5px;
height: 20px;
}
body form input:hover {
box-shadow: 0 0 5px #aaa;
}
body form button {
flex: auto;
height: 30px;
background-color: green;
color: white;
border: none;
outline: none;
}
body form button:hover {
background-color: lightcoral;
cursor: pointer;
box-shadow: 0 0 5px #aaa;
}
body a {
color: #888;
text-decoration: none;
margin-top: 15px;
}
body a:hover {
color: lightcoral;
font-weight: bold;
}
Session方式的用户登陆
index.php
<?php
// 开启会话
session_start();
// 判断是否已经登录?
if (isset($_SESSION['user'])) $user = unserialize($_SESSION['user']);
?>
<!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/index.css">
<title>首页</title>
</head>
<body>
<nav>
<a href="index.php">我的论坛</a>
<?php if (isset($user)) : ?>
<a href="" id="logout"><span style="color:red"><?php echo $user['name']?></span> 退出</a>
<?php else: ?>
<a href="login.php">登录</a>
<?php endif ?>
</nav>
</body>
<script>
// 为退出按钮创建事件监听器
document.querySelector('#logout').addEventListener('click', function(event) {
if (confirm('是否退出')) {
// 禁用默认行为, 其实就是禁用原<a>标签的点击跳转行为,使用事件中的自定义方法处理
event.preventDefault();
// 跳转到退出事件处理器
window.location.assign('handle.php?action=logout');
}
});
</script>
</html>
login.php
<?php
// 开启会话
session_start();
// 判断是否已登录
if (isset($_SESSION['user']))
exit('<script>alert("请不要重复登录");location.href="index.php";</script>');
?>
<!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>
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>
handle.php
<?php
// 开启会话
session_start();
// 查询用户表中的数据
$pdo = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root');
$stmt = $pdo->prepare('SELECT * FROM `users`');
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 处理用户登录与注册
$action = $_GET['action'];
switch ( strtolower($action)) {
// 登录
case 'login':
// 判断请求是否合t法
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 获取需要验证的数据
$email = $_POST['email'];
$password = sha1($_POST['password']);
$results = array_filter($users, function($user) use ($email, $password) {
return $user['email'] === $email && $user['password'] === $password;
});
if (count($results) === 1) {
$_SESSION['user'] = serialize(array_pop($results));
exit('<script>alert("验证通过");location.href="index.php"</script>');
} else {
exit('<script>alert("邮箱或密码错误,或者还没有帐号");location.href="login.php";</script>');
}
} else {
die('请求类型错误');
}
break;
// 退出
case 'logout':
if (isset($_SESSION['user'])) {
session_destroy();
exit('<script>alert("退出成功");location.assign("index.php")</script>');
}
break;
// 注册
case 'register':
// 1. 获取到所有新用户数据
$name = $_POST['name'];
$email = $_POST['email'];
$password = sha1($_POST['p1']);
$register_time = time();
// 2. 将新用户插入到表中
$sql = "INSERT `users` SET `name`='{$name}', `email`='{$email}', `password`='{$password}', `register_time`={$register_time}";
$stmt = $pdo->prepare($sql);
$stmt->execute();
if ($stmt->rowCount() === 1) exit('<script>alert("注册成功");location.assign("login.php")</script>');
else exit('<script>alert("注册失败");location.assign("login.php")</script>');
break;
// 未定义
default:
exit('未定义操作');
}
index.css
```css
nav {
height: 40px;
background-color: deepskyblue;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
nav > a {
color: white;
text-decoration: none;
}
style.css
body {
display: flex;
flex-direction: column;
text-align: center;
color: #555;
font-weight: 300;
}
body h3 {
font-weight: 300;
font-size: 20px;
margin-bottom: 10px;
}
body form {
width: 220px;
padding: 20px;
box-sizing: border-box;
background-color: skyblue;
margin: auto;
border-radius: 5px;
box-shadow: 0 0 5px #aaa;
}
body form > div {
height: 36px;
display: flex;
justify-content: space-between;
align-items: center;
}
body form div:last-of-type {
display: flex;
justify-content: center;
}
body form input {
border: none;
outline: none;
padding-left: 5px;
height: 20px;
}
body form input:hover {
box-shadow: 0 0 5px #aaa;
}
body form button {
flex: auto;
height: 30px;
background-color: green;
color: white;
border: none;
outline: none;
}
body form button:hover {
background-color: lightcoral;
cursor: pointer;
box-shadow: 0 0 5px #aaa;
}
body a {
color: #888;
text-decoration: none;
margin-top: 15px;
}
body a:hover {
color: lightcoral;
font-weight: bold;
}
课程学习小结
本次课程老师讲解非常细致,在老师的直播讲解之后,又通过回看视频进行理解消化,并在老师的课堂案例中实操了每一段代码予以加深理解,对用户登陆处理环节有了比较完整的认识,对以前不太敢看的整段代码,能够认真地看完并基本理解,有一定的进步。
复习过程中对本次课程中关于会话控制相关原理知识要点做了整理:Cookie:服务器端设置、保存在客户端的一个小变量,用来标识访问者的身份,是针对浏览器的,它不认识你是张三还是李四,它只认识你用的是什么样的访问代理,就是你用的是什么样的浏览器,它通过识别浏览器来识别当前访问用户是不是已经访问过了,如果你是第二次来,那我读一下看里面有没有Cookie,有的话就把它取出来,取到之后就知道你是否已经登录了,根据Cookie的值来进行判断,这就是一个典型的会话过程。Cookie类似于超市会员卡,实际卡片保存在用户手中(浏览器端),但随着发展,如果是电子卡包或只报手机号,就变成了存在商家手中(服务器端),这就是Session了。我们一般所说的会话控制,主要指的是Session,由服务器端设置,保存在服务器端。