PHP Session 会话


在本教程中,我们将学习如何使用PHP session在会话期间跨页面保存web应用程序的状态。

PHP会话是如何工作的

会话允许您在与会话ID关联的web服务器上存储数据。一旦创建了会话,PHP就会向web浏览器发送包含会话ID的cookie。在随后的请求中,web浏览器将会话ID cookie发送回web服务器,以便PHP能够根据会话ID查询数据,并使数据在脚本中可用。

PHP在哪里存储会话数据

默认情况下,PHP将会话数据存储在web服务器上的临时文件中。您可以在PHP配置文件中使用指令session.save_path指定临时文件的位置。

如果你想在脚本中查看它的设置,可以使用ini_get()函数如下:

1
2
<?php
echo ini_get('session.save_path');

获取会话数据存储文件位置的另一种方法是使用session_save_path()函数:

1
session_save_path()

通常,会话数据存储在web服务器的/tmp文件夹中。

如何创建会话

要创建一个会话,可以使用session_start()函数,如下所示:

1
2
<?php
session_start();

第一次在脚本中调用session_start()时,PHP生成一个惟一的会话ID,并以名为PHPSESSID的cookie的形式将其发送到web浏览器。
如果会话已经存在,PHP将检查浏览器发送的PHPSESSID cookie, session_start()函数将使用现有的会话。

需要注意的是,PHP必须在HTTP头文件中发送PHPSESSID cookie,因此,必须在将内容输出到web浏览器的任何语句之前调用session_start()函数。
否则,您将收到一条警告消息说您不能修改header信息,因为它已经被发送了。

即在session_start()前面不能echo,print或者有html代码或空白字符。

如何访问会话中的数据

与cookie不同,您可以在会话中存储任何类型的数据。将数据作为键和值存储在$SESSION[]超全局数组中。

例如,在index.php文件中,您将用户字符串和角色数组存储在会话中,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
session_start();
// 存储一个标量值
$_SESSION['user'] = 'admin';
 
// 存储一个数组
$roles = array('administrator','itroad','editor');
$_SESSION['roles'] = $roles;
 
session_write_close();
?>
 
<html>
<head>
<title>PHP Session演示</title>
</head>
<body>
<a href="profile.php">转到个人资料页面</a>
</body>
</html>

在profile.php文件中,可以用如下方式访问会话数据:

1
2
3
4
5
6
7
8
9
10
<?php
session_start();
 
if(isset($_SESSION['user'])){
echo sprintf("欢迎 %s!",$_SESSION['user']);
}
 
if(isset($_SESSION['roles'])){
echo sprintf('你的角色是: %s', implode($_SESSION['roles'],','));
}

在index.php文件中,您可以看到我们在将数据写入$_SESSION数组后使用session_write_close()函数。
它会强制将$_SESSION数组中的数据保存到web服务器上的会话数据文件中,并释放会话数据文件的锁。

通常,PHP在脚本结束时自动执行此操作。但是,当不再将数据写入$_SESSION[]数组时,最好调用session_write_close()函数。
原因是当您使用基于文件的会话时,每个请求都会锁定文件,直到它被终止。在随后的请求中,脚本需要等待锁被释放,以便再次访问会话数据。
锁用于防止会话数据损坏。但是,对于经常'假死'的脚本,脚本执行必须等待太长时间。session_write_close()函数帮助提前释放锁,并允许下一个脚本继续运行,而不必等待锁释放。

如何销毁会话

当用户关闭浏览器时,PHP会自动删除会话,因为PHPSESSID cookie的expires字段被设置为0。
然而,在某些情况下,我们想手工销毁会话,例如,当用户单击注销链接时。
要销毁会话,可以使用session_destroy()函数。

1
2
<?php
session_destroy();

session_destroy()将销毁与当前会话关联的所有数据。但是,它不会unset $_SESSION数组和cookie中的数据。

要完全销毁会话数据,取消$_SESSION数组中的变量设置并删除PHPSESSID cookie,您可以使用以下代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
session_start();
 
// 删除cookie
if(isset($_COOKIE[session_name()])){
setcookie(session_name,'',time() - 3600, '/');
}
 
// unset $_SESSION中的数据
$_SESSION[] = array();
 
// 销毁会话
session_destroy();

注意,我们使用session_name()来获取cookie名,而不是使用PHPSESSID。这是因为PHP允许您在同一个脚本上处理多个具有不同名称的会话。

简单的登录系统

我们将使用我们所介绍的技术来开发一个简单的登录系统。你可以自己尝试一下,分析一下它是如何工作的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php
session_start();
 
define("SYSUSER",'admin');
define("SYSPASSWORD",'secret');
 
start();
 
/**
* 开始处理登录表单
*/
function start(){
if(isset($_POST['login'])){
if(authenticate()){
// 如果用户成功登录,则显示受保护的内容
display_secured_content();
}else{
// 再次显示登录表单和消息
display_login_form('无效的用户名或密码。');
}
}else if(isset($_GET['action']) && $_GET['action'] == 'logout'){
logout();
}else{
display_login_form();
}
}
 
/**
* 显示登录表单。如果传递了$msg,则将其显示为错误消息
* @param string $msg error message
*/
function display_login_form($msg=''){
?>
<style>
.error {
color: #ff0000;
}
</style>
<form action="login.php" method="post">
<p class="error">
<?php echo $msg; ?>
</p>
<fieldset name="logininfo">
<legend>Login</legend>
<label for="username">Username:</label>
<input type="text" name="username" id="username" /><br />
<label for="password">Password:</label>
<input type="password" name="password" id="password" /><br />
<input type="submit" name="login" value="Login">
</fieldset>
</form>
<?php
}
 
/**
* 向登录用户显示受保护的内容
*/
function display_secured_content(){
?>
<h1>
Welcome
<?php echo $_SESSION['username'];?>
</h1>
<p>欢迎来到会员区!</p>
<p>
<a href="login.php?action=Logout">logout</a>
</p>
<?php
}
 
/**
* 验证用户的输入
* @return 如果用户身份验证成功,则返回true,否则返回false
*/
function authenticate(){
if(isset($_POST['username']) && isset($_POST['password'])){
$username = $_POST['username'];
$password = $_POST['password'];
 
if($username == SYSUSER && $password == SYSPASSWORD){
$_SESSION['username'] = SYSUSER;
session_write_close();
return true;
}
else{
return false;
}
}
}
/**
* 退出logout
*/
function logout(){
if(isset($_COOKIE[session_name()])){
setcookie(session_name,'',time() - 3600, '/');
}
$_SESSION = array();
session_destroy();
 
header('location: login.php');
}


原文链接:https://codingdict.com/