前言-关于为什么会有这篇文章
那当然是因为我想要水篇文章啦
咳咳,还不是因为某个Final Mission,写完了当然来水一篇文章咯(

关于前端
当写到这里的时候,忽然想起来之前做的某道web题的前端还行,于是就偷过来咯(x)
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
| <!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Rabbit House 成员管理系统</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="content container pt-5"> <h1>Rabbit House 成员管理系统</h1> <form method="post" action="."> <div class="form-group"> <label> 用户名:<input type="text" class="form-control" name="username"> </label> </div> <div class="form-group"> <label> 密码:<input type="password" class="form-control" name="password"> </label> </div> <button type="submit" class="btn btn-primary">登录</button> </form> </div> </body> </html>
|
数据库部分
考虑到这个项目的要求有登录,注销以及留言功能,所以需要用到数据库。我建立的数据表结构如下:

首先建一个final_database
来存放这个项目的数据。
final_user 结构如下:

username
显然是用户的id,password
用来保存用户的密码,按照需要也可以保存密码的md5,head_path
保存用户的头像路径。
msg_book 结构如下:

username
是用户id,post_time
保存用户留言的时间,text
是用户留言的内容,最后的post_time
是偷个懒,用户留言时直接把头像路径保存,略去输出用户留言时再去查询头像。
user_auth 结构如下:

username
是用户id,再用户登陆时会随机生成一串数字作为验证,随机数保存于userauth
,登陆时间保存于authtime
。
项目包含文件
由于项目各个模块基本都要用到cookie,mysql查询等功能,为了提高代码的复用率,所以这些代码写到一个文件,各个部分再包含这个文件。
常量定义
1 2 3 4 5 6 7 8 9 10
| define("MYSQL_HOST", "**.**.**.**"); define("MYSQL_USERNAME", "*********"); define("MYSQL_PASSWORD", "********"); define("MYSQL_DATABASE", "final_database");
define("TABLE_USERLIST", "final_user"); define("TABLE_MSGBOOK", "msg_book"); define("TABLE_USERAUTH", "user_auth");
|
cookie部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
session_start();
$isLogin = false; if(isset($_COOKIE['username'])){ $isLogin=true; $user_name = $_COOKIE['username']; $head_path = $_COOKIE['headpath']; $user_auth = $_COOKIE['userauth']; } else{ $isLogin=false; }
|
mysql部分
1 2
| $link = mysqli_connect(MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWORD, MYSQL_DATABASE);
|
MySql部分就相对比较简单了,后面需要查询的时候都是单独写的。。
防XSS攻击模块
由于用户的id和留言内容都是直接使用用户提交的字符串,就存在xss攻击的风险,所以要对用户提交的内容进行过滤。
1 2 3 4 5 6 7
| function anti_xss($text){ $text_anti_xss = trim($text); $text_anti_xss = strip_tags($text_anti_xss); $text_anti_xss = htmlspecialchars($text_anti_xss); $text_anti_xss = addslashes($text_anti_xss); return $text_anti_xss; }
|
用户登录验证模块
在用户登录之后发表信息的时候验证用户身份的部分,,,emm算了不描述了(
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
| function auth_check($auth, $name, $link){ $sql = "SELECT * FROM `".TABLE_USERAUTH."` WHERE username = '$name'"; $res = mysqli_query($link, $sql); $arr = mysqli_fetch_assoc($res); if($arr){ if($arr['userauth']==$auth && $arr['authtime'] + 3600 > time()){ return 1; } else { return 0; } } else { return -1; } }
function auth_insert($auth, $name, $link){ $tmp = auth_check($auth, $name, $link); if($tmp >= 0){ $sql2 = "UPDATE `user_auth` SET `userauth` = '$auth', `authtime` = '".time()."' WHERE `user_auth`.`username` = '$name'"; mysqli_query($link, $sql2); } else if($tmp == -1){ $sql2 = "INSERT INTO `".TABLE_USERAUTH."` (`username`, `userauth`, `authtime`) VALUES ('$name', '$auth', '".time()."')"; mysqli_query($link, $sql2); } }
|
具体讲解之后再补吧emm
用户登录部分设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function user_login($username, $password, $link){ $sql = "SELECT * FROM `final_user` WHERE username = '$username'"; $res = mysqli_query($link, $sql); $arr = mysqli_fetch_assoc($res); $password_md5ed = md5($password); if($arr){ if($arr['password']==$password_md5ed){ $auth_tmp = rand(1000000,9999999); setcookie("username",$_POST["username"],time()+3600); setcookie("headpath",$arr["head_path"],time()+3600); setcookie("userauth",$auth_tmp,time()+3600); auth_insert($auth_tmp, $username, $link); echo"<script>alert('登录成功!');location.href = 'index.php';</script>"; }else{ echo"<script>alert('密码错误!');location.href = 'index.php';</script>"; } }else{ echo "<script>alert('".$username."');</script>"; echo"<script>alert('用户名不存在,请先注册!');location.href = 'index.php';</script>"; } }
|
在收到用户的登录请求时,通过提交的用户名查询到密码的md5值,然后再将密码md5之后进行比较。登录成功后进行cookie的设置和用户auth信息的更新。
用户注册部分设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function user_register($username, $password, $link){ $username_anti_xss = anti_xss($username); $sql = "SELECT * FROM `".TABLE_USERLIST."` WHERE username = '$username_anti_xss'"; $res = mysqli_query($link, $sql); $arr = mysqli_fetch_assoc($res); if($arr){ echo"<script>alert('用户名已存在!');location.href = 'index.php';</script>"; }else{ $password_md5ed = md5($password); $sql2 = "INSERT INTO `".TABLE_USERLIST."` (`username`, `password`, `head_path`) VALUES ('$username_anti_xss', '$password_md5ed', NULL)"; mysqli_query($link, $sql2); echo"<script>alert('注册成功!');location.href = 'index.php';</script>"; } }
|
和用户登录部分大体一致
用户登出部分设计
1 2 3 4 5 6
| function user_logout(){ setcookie("username",$user_name,time()-3600); setcookie("headpath",$head_path,time()-3600); setcookie("userauth",$user_auth,time()-3600); echo "<script>alert('注销成功!');location.href = 'index.php';</script>"; }
|
在用户登出时删除所有cookie,还应该更新下用户的auth信息的,之后再补吧emmm
发布留言部分设计
1 2 3 4 5 6
| function post_msg($text, $username, $headpath, $link){ $text_anti_xss = anti_xss($text); $sql2 = "INSERT INTO `".TABLE_MSGBOOK."` (`username`, `post_time`, `text`, `post_head`) VALUES ('$username', CURRENT_TIMESTAMP, '$text_anti_xss', '$headpath')"; mysqli_query($link, $sql2); echo"<script>alert('发送成功!');location.href = 'index.php';</script>"; }
|
代码言简意赅,就这样吧(
上传头像部分设计
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
| function post_img($img, $username, $link){ $tmp_dir=$img['tmp_name']; $fileName=$img['name']; if($img['error']!=0){ echo '上传文件出现错误!请重试!'; return; }else if($img['size']>10240000){ echo "文件超过".$maxSize; return; }else if($img['size']<20480){ echo "上传文件出现错误!请重试!"; return; }else{ $fileDir='./upload/'; if(!is_dir($fileDir)){ mkdir($fileDir); } $newFileName=date('YmdHis',time()).rand(100,999); $FileExt=substr($fileName,strrpos($fileName,'.')); $FilePath=$newFileName.$FileExt;
$img_info=getimagesize($tmp_dir); $width=$img_info[0]; $height=$img_info[1]; $newWidth=$width*0.5; $newHeight=$height*0.5;
$thumb=imagecreatetruecolor($newWidth, $newHeight); $source=imagecreatefromjpeg($tmp_dir);
imagecopyresized($thumb,$source,0,0,0,0,$newWidth,$newHeight,$width,$height);
imagejpeg($thumb,'./upload/'.$newFileName.$FileExt,100);
move_uploaded_file($tmp_dir,'./upload/'.$newFileName.'_temp'.$FileExt); unlink('./upload/'.$newFileName.'_temp'.$FileExt); $sql2 = "update final_user set `head_path`='$FilePath' WHERE username = '$username'"; mysqli_query($link, $sql2); setcookie("headpath",$FilePath,time()+3600); echo "<script>alert('上传成功!');location.href = 'index.php';</script>"; } }
|
为了避免文件上传存在的风险,于是选择在用户上传图片后进行压缩,从而避免文件上传的风险。
接下来就是各个部分的前端了
首页部分 index.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
| <!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Rabbit 留言本 ^ - ^</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="content container pt-5"> <h1>Rabbit 留言本 ^ - ^</h1> <p>本站提供注册,登录,留言板功能!</p> <?php include "include.php"; if ($isLogin) { echo "你好! ".$user_name.' ,欢迎来到个人中心!<br>'; echo "<img src=\"./upload/$head_path\" width=50 height=50> "; echo "<a class=\"btn btn-warning\" href='logout.php'>注销</a> "; echo "<a class=\"btn btn-warning\" href='upimg.html'>上传/修改头像</a>"; } else { echo "您还没有登录,请先登录!</a>"; } ?> <form method="post" action="login.php" <?php if ($isLogin)echo "hidden"?>> <div class="form-group"> <label> 用户名:<input type="text" class="form-control" name="username"> </label> </div> <div class="form-group"> <label> 密码:<input type="password" class="form-control" name="password"> </label> </div> <button type="submit" class="btn btn-primary">登录</button> <a class="btn btn-success" href="register.php">没有id?点击注册</a> </form> <div id="loged" <?php if (!$isLogin)echo "hidden"?>> <p>test233</p> <table border="1" width=80%> <tr> <td>Test</td> <td width=80%>test message</td> </tr> <?php //输出留言信息 $query='select * from msg_book'; $result=mysqli_query($link, $query); //echo '<br> <br>'; while ($data=mysqli_fetch_assoc($result)){ echo '<tr>'; echo '<td>'; echo "<img src=\"./upload/".$data[post_head]."\" width=50 height=50> <br> $data[username] <br> "; echo $data[post_time]; echo '</td>'; echo '<td>'.$data[text].'</td>'; } ?> <tr> <td>Admin<br>2019-11-3 22:45</td> <td width=80%>Welcome!</td> </tr> <tr> <td colspan="2"> <form name="input" action="postmsg.php" method="post"> 回复内容: <input type="text" name="text"> <input type="submit" value="Submit"> </form> </td> </tr> </table> </div> <br> <p>本站仅供学习使用,请勿用于任何非法用途!<del>更不要日站!!!</del></p>
</div> </body> </html>
|
判断用户是否登录来对对部分内容进行隐藏,中间通过查询留言本按照表格输出数据。
注册页面 register.php
(注:后面html部分基本相同所以只写body部分了。。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php header('content-type:text/html;charset=utf-8'); include "include.php"; if ($isLogin) { echo"<script>alert('您已经登录请不要重复注册!');location.href = 'index.php';</script>"; }
if(isset($_POST['username'])){ $name = $_POST["username"]; $pwd = $_POST["password"]; user_register($name, $pwd, $link); } ?>
|
登录页面 login.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php header('content-type:text/html;charset=utf-8'); include "include.php";
if ($isLogin) { echo"<script>alert('您已经登录请不要重复登录!');location.href = 'index.php';</script>"; }
$name = $_POST["username"]; $pwd = $_POST["password"]; user_login($name, $pwd, $link); ?>
|
登出页面 louout.php
1 2 3 4 5
| <?php header('content-type:text/html;charset=utf-8'); include "include.php"; user_logout(); ?>
|
发布留言页面 postmsg.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php header('content-type:text/html;charset=utf-8'); include "include.php";
if (!$isLogin) { echo"<script>alert('您还没有登录!');location.href = 'index.php';</script>"; exit(); }
if(auth_check($user_auth, $user_name, $link)!=1){ echo"登陆信息出错,信息提交失败!"; exit(); }
$text = $_POST["text"]; $name = $_COOKIE["username"]; $hdpath=$_COOKIE['headpath'];
post_msg($text, $name, $hdpath, $link); ?>
|
上传头像页面
upimg.html
1 2 3 4 5 6
| <body> <p>建议上传jpg格式图片。</p> <form action="upImg.php" method="post" enctype="multipart/form-data"> <input type="file" name="userImg" > <input type="submit" value="上传"> </form>
|
upimg.php
1 2 3 4 5 6 7 8 9
| <?php header('content-type:text/html;charset=utf-8'); date_default_timezone_set("PRC"); include "include.php"; $img=$_FILES['userImg']; post_img($img, $user_name, $link); ?>
|
之后,是这个项目的一些参考:
PHP上传用户头像及头像的缩略图
PHP防XSS攻击
b站之前学php的视频(的笔记)
项目已上传至github,欢迎一起来玩鸭~
https://github.com/panedioic/rabbit_msgbook