登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】

写在前面

当登录时究竟发生了什么?如何去追踪关键信息,关键信息又在哪里?看了很多不管是http基本认证还是session的机制,体会不够深,还是不如自己边写边理解和记忆来的深刻。
参考资料:《PHP、MySQL与JavaScript学习手册》 第五版 --中国电力出版社
希望能对你理解登陆身份识别上有所帮助。

基础知识

这里仅简单说一说。
cookie在首部中交换,在网页的html内容之前发送,html一旦发送,就无法再发送cookie了。
例如:
1.浏览器发起请求,请求头会指定请求文件路径和服务器
2.服务器收到这些首部后,也会返回首部,这里返回的首部之一,就有Set-cookie: name=value
3.收到cookie后,后续每次对签发服务器的请求都会带上cookie,就是Cookie: name=value
4.服务器收到带cookie的请求,不再发送cookie,返回被请求的页面。

资料引用:

由于 Session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。实际上在服务器端的 Session 文件,PHP 自动修改 Session 文件的权限,只保留了系统读和写权限,而且不能通过 ftp 修改,所以安全得多。

对于 Cookie 来说,假设我们要验证用户是否登陆,就必须在 Cookie 中保存用户名和密码(可能是 md5 加密后字符串),并在每次请求页面的时候进行验证。如果用户名和密码存储在数据库,每次都要执行一次数据库查询,给数据库造成多余的负担。因为我们并不能 只做一次验证。为什么呢?因为客户端 Cookie 中的信息是有可能被修改的。假如你存储 $admin 变量来表示用户是否登陆,$admin 为 true 的时候表示登陆,为 false 的时候表示未登录,在第一次通过验证后将 $admin 等于 true 存储在 Cookie,下次就不用验证了,这样对么?错了,假如有人伪造一个值为 true 的 $admin 变量那不是就立即取的了管理权限么?非常的不安全。

而 Session 就不同了,Session 是存储在服务器端的,远程用户没办法修改 Session 文件的内容,因此我们可以单纯存储一个 $admin 变量来判断是否登陆,首次验证通过后设置 $admin 值为 true,以后判断该值是否为 true,假如不是,转入登陆界面,这样就可以减少很多数据库操作了。而且可以减少每次为了验证 Cookie 而传递密码的不安全性了(Session 验证只需要传递一次,假如你没有使用 SSL 安全协议的话)。即使密码进行了 md5 加密,也是很容易被截获的。

资料参考链接:https://blog.csdn.net/a5605005/article/details/101153131

程序一

这里不再涉及到http基本身份认证,基本身份认证具有一定的漏洞,同时运用范围不算很广。这里我们直接使用session版的登陆方法。
首先来test一下,查看一下session的结构,脚本:


	session_start();
	
	$_SESSION['admin']=null;

在网页中执行一下(网页上是一片白),抓包看看:
登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第1张图片
这里进行了session_id的设置,当我们请求localhost的其他相关资源时,就会带上刚才设置过的session_id,就像这样:

登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第2张图片
session就开始工作了,在服务器上看看session的样子:
文件类似如下:
在这里插入图片描述
如果你也想在本地服务器查看,一般会存放在tmp目录下,可以找找。

查看后保存结果如下:

admin|N;

保存规则:
变量名|类型:长度:值; 并用分号隔开每个变量。有些是可以省略的,比如长度和类型。

程序二

来一个完整的登陆程序,由于我们这里只讨论session。这里的html,数据库等等操作就略过了,找了其他同学的资源:

index.php

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>php登录测试</title>
	</head>
	
	<body>
		<form action="register.php" method="POST" >
		
			<label>用户名:</label>
			<input type = "text" name = "username"/> <br/>
			
			<label>密码:</label>
			<input type = "password" name="password"/> <br/>
			
			<input type = "submit" value = "提交"/>
			
		</form>
	</body>
</html>

register.php


	header("Content-type: text/html; charset=utf-8");
	session_start(); //session开始

	//$_POST用户名和密码
	$username = $_POST['username'];
	$password = $_POST['password'];
	
	//连接mysql
	$con = mysqli_connect('localhost','root','', '');
	//验证mysql连接是否成功
	if(mysqli_errno($con)){
		echo "连接mysql失败:".mysqli_error($con);
		exit;
	}
	//sql查询语句
	$sql = "select id from security.users where username='$username' and password='$password'";
	//执行
	$result = mysqli_query($con,$sql);
	$num = mysqli_num_rows($result); // 函数返回结果集中行的数量
	if($num){
		echo "";
	} else{
		die( "");
	}
	
	$row = mysqli_fetch_assoc($result);
	$_SESSION['userid'] = $row['id']; // session值设置
	
	mysqli_close($con);
	
	echo "";
?>

show.php


	header("Content-type: text/html; charset=utf-8");
	session_start();
	$userid = $_SESSION['userid']; // 读取前面设置的session值
	//连接mysql
	$con = mysqli_connect('localhost','root','', '');
	//验证mysql连接是否成功
	if(mysqli_errno($con)){
		echo "连接mysql失败:".mysqli_error($con);
		exit;
	}
	//sql查询语句
	$sql = "select username from security.users where id='{$userid}'";
	//执行
	$result = mysqli_query($con,$sql);
	$row = mysqli_fetch_assoc($result);
	$name = $row['username'];
	$talk= 'i am talk';
	mysqli_close($con);
?>
<!DOCTYPE html>
<html>
	<head>
		<title>用户信息</title>
	</head>
	
	<body>
		<p>
			用户名:
			<?php  
				echo $name;
			?>
		</p>
		
		<p>
			个人简介:
			<?php  
				echo $talk;
			?>
		</p>
	</body>
</html>

数据库构建

登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第3张图片

注:如果你要在自己的环境上复现,注意修改数据库密码和连接的库,还有相关字段的修改。

普通运行展示

登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第4张图片
分别输入 123 123
登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第5张图片
返回输入 admin admin123(数据库里设置的账号密码)
登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第6张图片
登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第7张图片
基本功能完成

抓包查看

上面例子要重点关注关于session的注释,如果你仔细看,session在这里起到了一个公共量传递的作用,让键值对可以跨网页(文件)使用。
登陆身份识别机制(Session工作机制,PHP版)【含登陆程序脚本】_第8张图片
这里我们已经设置过一个session
发出请求时就会带上PHPSESSID,由唯一的session_id来表示独属于当前用户的session。这样就能够靠session传递个性化信息了。
这里我们的session_id是 k34lhop0qudc0nudm38oblp933
我们从服务器端直接读取更加直接的看看
tmp下找到;
在这里插入图片描述
打开:
在这里插入图片描述
就是传递了我们设置的userid
以上就是session在变量传递中的作用。

程序三

当然session另一个作用就是权限维护,在登陆完成后的session生效期间,可以不必再次登录,维护一定时间的权限。
由于写的时候隔了一天,优化了一点点。
register.php 当中,当查询到有效值之后,改成这样:

$result = mysqli_query($con,$sql);
	$num = mysqli_num_rows($result); // 函数返回结果集中行的数量
	
	if($num)
	{
		echo "";
		session_start();
		$row = mysqli_fetch_assoc($result);
		$_SESSION['admin']=true;
		$_SESSION['userid'] = $row['id']; // session
	
	} 
	else
	{
		die( "");
	}

这里将session操作放入了if中,同时对session多了一步操作:

$_SESSION['admin']=true;

然后在index.php的前面加上这个(因为要用php,又改成php后缀了)

  
    $admin=false;
    session_start();
    if(isset($_SESSION['admin'])===true)
    {
        echo "";
    }
?>

这其实就是一个简单的验证程序,如果你的session符合要求,就可以直接进入后续界面,如果不符合要求,就会进入常规登录界面。
当然,这样可以放在任何你想要验证是否登录的界面上。
测试结果当然就是,当你登录成功后的一段时间内,可以无需登录,直接进入show.php
权限维持就成功了

延伸

如果我们还有一个注销下线的功能,那当然就需要将当前的session摧毁。后续优化一下再写新的。

你可能感兴趣的:(网络安全,php,服务器,session,mysql,网络安全)