php注册登录系统开发实战

php用户注册登录系统之验证码制作

验证码的分析

登录注册页面设置验证码主要是为了防止暴力破解、恶意注册等情况的发生,是属于网站的标配内容,到今天已经发展成将验证码直接发送到用户手机或者邮箱进行验证,本节只做最简单的图片验证码的验证,大家可以通过本节,了解验证码验证的原理


生成验证码的简单流程图

生成验证码的流程图.png

具体的实现见下面的内容


生成验证码背景图

1.开启php的GD扩展

打开php.ini文件,将extension=php_gd2.dll这一项的注释去掉,开启它,如果本来是开启的则不需要改动

p1.png

接下来,我们来制作一个60X15的白色背景图片

2.创建画布

画布,一种资源型数据。可以操作的图像资源。

  • 创建新画布(新建)
ImageCreate(宽,高),创建基于调色板的画布。

imageCreateTrueColor(宽,高);创建真彩色的画布。
  • 基于图片创建画布(打开)
imageCreateFromJPEG(图片地址);

imageCreateFromPNG(图片地址);

imageCreateFromGIF(图片地址);

我们创建一个真彩色的画布:

*$width=60;
$height=15;
//创建画布
$img=imageCreateTrueColor($width,$height);*

大家可以尝试使用var_dump();$img输出查看其类似是不是资源型

3.操作画布

分配颜色:如果需要在画布上使用某个颜色,应该先将颜色分配到画布上。

使用函数:

颜色标识 = imageColorAllocate(画布,R,G,B);

*//分配颜色
$white = imageColorAllocate($img,0xff,0xff,0xff);*

填充画布:将填充点,连续并且颜色相同的点进行填充(替换)

使用函数:

imageFill(画布, 填充位置x, 填充位置Y,颜色标识)完成

位置采用坐标进行管理:

原点:0,0,画布的左上角。

向右,x轴增加,向下Y轴增加。

*//填充颜色到画布
imageFill($img,0,0,$white);*

4.输出画布

将画布中处理好的图样信息,输出出来。

典型的:

  • 输出到图片文件。

  • 直接输出。

使用函数:

imagePNG(画布[, 文件地址])://在指定地址生成文件

imageJPEG();//在网页上直接输出,我们的验证码采用这种方式

imageGIF();//同上一个

如果没有第二个参数,表示直接输出。

直接输出到浏览器,需要告知浏览器,响应数据的类型应该是PNG格式的图片:

使用指令Content-type

*//直接输出*

*header('Content-Type:image/jpeg;');*

*imageJPEG($img);*

注:一个画布可以输出多次,输出为各种格式!

5.销毁画布资源

使用函数:imageDestroy();

*imageDestroy($img);*

生成验证码的值

1.首先必须定义所以可能出现的字符,获取所有字符的总长度以及我们要生成的验证码的长度

代码如下:

*//生成验证码的值
$chars = '1234567890';//所以可能出现的字符
$chars_len=strlen($chars);
$code_len=4;//验证码的长度
$code='';//初始化验证码字符串*

2.分四次,每次从所有可能出现的字符中取出一个数字,最后将四位数字链接在一起,生成验证码的值

*for($i=1;$i<=$code_len;++$i){
    $rand=mt_rand(0,$chars_len-1);//随机取0-9中的任意一个数字
    $code.=$rand;//将取出来的数字连接在一起
}*

3.开启session,将验证码值存入session中,用于验证

*//存入session中,用于验证-------------------------
session_start();
$_SESSION[' ver_code']=$code;*

将验证码值放入验证码背景图片中

1.给验证码值分配随机颜色

*//随机分配字符串颜色
$str_color=imageColorAllocate($img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));*

2.使验证码值居中写在背景图上面

*//计算字符串的居中
//字符串大小
$font=5;
//画布尺寸
$img_w=imageSX($img);
$img_h=imageSY($img);
//字体的尺寸
$font_w=imagefontwidth($font);
$font_h=imagefontheight($font);
//字符串的尺寸
$code_w=$font_w*$code_len;
$code_h=$font_h;
$x=($img_w-$code_w)/2;
$y=($img_h-$code_h)/2;
//把验证码输出到画布上----------------------------
imageString($img,$font,$x,$y,$code,$str_color);*

3.输出验证码

*//直接输出
imageJPEG($img);
imageDestroy($img);*

完整代码如下

<?php
//生成验证码背景图---------------------------------
header('Content-Type:image/jpeg;');
//背景图尺寸
$width=60;
$height=15;
//创建画布
$img=imageCreateTrueColor($width,$height);
//分配颜色
$white = imageColorAllocate($img,0xff,0xff,0xff);
//填充颜色到画布
imageFill($img,0,0,$white);
//生成验证码的值----------------------------------
$chars = '1234567890';//所以可能出现的字符
$chars_len=strlen($chars);
$code_len=4;//验证码的长度
$code='';//初始化验证码字符串
for($i=1;$i<=$code_len;++$i){
    $rand=mt_rand(0,$chars_len-1);//随机取0-9中的任意一个数字
    $code.=$rand;//将取出来的数字连接在一起
}
//存入session中,用于验证-------------------------
session_start();
$_SESSION['ver_code']=$code;
//随机分配字符串颜色------------------------------
$str_color=imageColorAllocate($img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
//计算字符串的居中
//字符串大小
$font=5;
//画布尺寸
$img_w=imageSX($img);
$img_h=imageSY($img);
//字体的尺寸
$font_w=imagefontwidth($font);
$font_h=imagefontheight($font);
//字符串的尺寸
$code_w=$font_w*$code_len;
$code_h=$font_h;
$x=($img_w-$code_w)/2;
$y=($img_h-$code_h)/2;
//把验证码输出到画布上----------------------------
imageString($img,$font,$x,$y,$code,$str_color);
//直接输出
imageJPEG($img);
imageDestroy($img);
?>

php用户注册登录系统之数据库搭建

创建数据库分析

本版本数据库在前一个版本id 、username 、userpwd 的基础上增加了createtime(创建时间)和createip(创建时的ip),密码采用md5加密之后存入数据库

字段详细信息如下:

| 字段名 | id | username | userpwd | createtime | createip |
| 字段类型 | int | varchar | varchar | int | int |
| 字段长度 | 11 | 30 | 32 | 11 | 11 |
| 字段描述 | 编号 | 用户名 | 密码 | 创建时间 | Ip地址 |

在命令提示符窗口下运行 mysql

安装好MySQL,我们可以通过cmd连接mysql

点击桌面右下角开始按钮(以我的window7为例)

m1.png

点击进入,输入cmd,点确定

m2.png

进入命令行界面,首先我们需要找到我们的MySQL程序,命令行默认在C盘,我们输入D:进入D盘

(因为我的MySQL安装在D盘,安装路径为D:\phpStudy\MySQL\bin)

注:命令行模式下想要粘贴的话只能使用鼠标右键,不能使用使用Ctrl+V

m3.png

接下来输入cd D:\phpStudy\MySQL\bin点击回车,进入MySQL安装文件的bin文件夹

m4.png

输入mysql -hlocalhost -uroot -proot ,回车后,会显示成功

m5.png

这时候,我们就能在里面输入sql语句了

注:每一行指令结束都有一个“;”


创建数据库的语句

我们已经写好了创建数据库的语句,大家只要将其复制,粘贴进命令提示符窗口中mysql>的后面,点击回车即创建成功:

m6.png

输入show tables;显示我们创建的user表:

m7.png

输入desc user;则显示user表的结构

m8.png

创建数据库的完整语句

DROP DATABASE IF EXISTS userdb;
CREATE DATABASE userdb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE userdb;
CREATE TABLE user(
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(30) DEFAULT NULL,
userpwd varchar(32) DEFAULT NULL,
createtime int(11) NOT NULL,
createip int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
insert into user(username,userpwd) values('admin','admin');

语句详解:

1.判断是否存在数据库userdb,存在则删除

2.创建userdb数据库,设定编码方式为utf8

3.选择创建的userdb库

4.创建一个user表,表里面有五个字段,分别是id编号、用户名、密码、创建事件、创建时使用的ip

5.定义存储引擎为MyISAM,user表的编码为utf8。

6.插入一条语句用于开始测试登录使用

php用户注册登录系统之登录注册页面

登录页面

代码如下:

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <title>登陆</title>
 <script>
 function init(){
    if(myform.username.value=="")
    {
        alert("请输入用户名");
        //将光标移动到文本框中
        myform.username.focus();
        return false;
    }
    if (myform.userpwd.value=="")
    {
        alert("请输入密码");
        myform.userpwd.focus();
        return false;
    }
    if (myform.code.value=="")
    {
        alert("请输入验证码");
        myform.code.focus();
        return false;
    }
}
</script>
<style type="text/css">
    .code{
        width:80px;
    }
    .titl{
        font-weight:bold;
        font-size:20px;
        position:relative;
        left:50px;
    }
    .bd{
        background-color:#f0f0f0;
        width:230px;
    }
</style>
</head>
<body>
<form action="logincheck.php" method="post" onsubmit="return init();" name="myform" >
<div class="bd">
    <div class="titl">用户登录</div>
    <div >
        <span >用户名:</span>
        <span><input type="text" name="username" id="username" placeholder="请输入用户名" /></span>
    </div>
    <div >
        <span >密&#12288码:</span>
        <span><input type="password" name="userpwd" id="userpwd" placeholder="请输入密码" ></span>
    </div>
    <div>
        <span >验证码:</span>
        <span><input type="text" name="code" class="code" id="code" placeholder="请输入验证码"></span>
        <span><img src="pic.php" onClick="this.src='pic.php?nocache='+Math.random()" style="cursor:pointer"></span>
    </div>
    <div >
        <span><button class="button">立即登陆</button></span>
        <span><a href="register.php">注册</a></span>
    </div>
    <span><input  type = "hidden" name = "hidden"  value = "hidden"  /></span>
</form>
</body>
</html>

代码解释:

from表单里面第一版采用了table进行布局,这一版采用了div布局

表单的属性增加了placeholder属性,提供可描述输入字段预期值的提示信息

增加了验证码,使用<img>标签引入,绑定了一个onclick事件,点击图片的时候刷新图片,style="cursor:pointer"是设定了鼠标移动到验证码图片时,鼠标箭头变小手形状

点击登录时onsubmit事件触发,判断每个<input>里面是不是为空,为空则将光标移动到该<input>,然后返回false,不执行提交操作

增加了一个隐藏域,用于处理页面的第一层判断,如果不存在的话,则提交不成功,不用进行后续判断了

注册页面

代码如下:

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <title>注册</title>
 <script>
 function init(){
    if(myform.username.value=="")
    {
        alert("请输入用户名");
        //将光标移动到文本框中
        myform.username.focus();
        return false;
    }
    if (myform.userpwd.value=="")
    {
        alert("请输入密码");
        myform.userpwd.focus();
        return false;
    }
    if (myform.confirm.value=="")
    {
        alert("请再输入一次密码");
        myform.confirm.focus();
        return false;
    }
    if (myform.code.value=="")
    {
        alert("请输入验证码");
        myform.code.focus();
        return false;
    }
}
</script>
<style type="text/css">
    .code{
        width:80px;
    }
    .titl{
        font-weight:bold;
        font-size:20px;
        position:relative;
        left:50px;
    }
    .bd{
        background-color:#f0f0f0;
        width:230px;
    }
</style>
</head>
<body>
<form action="regcheck.php" method="post" onsubmit="return init();" name="myform" >
<div class="bd">
    <div class="titl">用户注册</div>
    <div >
        <span >用&nbsp&nbsp户&nbsp名:</span>
        <span><input type="text" name="username" id="username" placeholder="请输入用户名" /></span>
    </div>
    <div >
        <span >密&#12288&#12288码:</span>
        <span><input type="password" name="userpwd" id="userpwd" placeholder="请输入密码" ></span>
    </div>
    <div >
        <span >确认密码:</span>
        <span><input type="password" name="confirm" id="confirm" placeholder="请再输入一次密码" ></span>
    </div>
    <div >
        <span >验&nbsp&nbsp证&nbsp码:</span>
        <span><input type="text" name="code" class="code" id="code" placeholder="请输入验证码"></span>
        <span><img src="pic.php" onClick="this.src='pic.php?nocache='+Math.random()" style="cursor:pointer"></span>
    </div>
    <div >
        <span><button class="button">立即注册</button></span>
    </div>
    <span><input  type = "hidden" name = "hidden"  value = "hidden"  /></span>
</form>
</body>
</html>

代码解释:

from表单里面第一版采用了table进行布局,这一版采用了div布局

表单的属性增加了placeholder属性,提供可描述输入字段预期值的提示信息

增加了验证码,使用<img>标签引入,绑定了一个onclick事件,点击图片的时候刷新图片,style="cursor:pointer"是设定了鼠标移动到验证码图片时,鼠标箭头变小手形状

点击登录时onsubmit事件触发,判断每个<input>里面是不是为空,为空则将光标移动到该<input>,然后返回false,不执行提交操作

增加了一个隐藏域,用于处理页面的第一层判断,如果不存在的话,则提交不成功,不用进行后续判断了

php用户注册登录系统之注册处理页面

注册处理页面

流程图如下:

第二版注册.png

详细代码如下:

<?php  
session_start();
//注册处理界面 regcheck.php
    if(isset($_POST["hidden"]) && $_POST["hidden"] == "hidden")  
    {  
        $user = trim($_POST["username"]);//trim()函数移除字符串两侧的空白字符
        $psw = md5(trim($_POST["userpwd"]));  
        $psw_confirm = md5(trim($_POST["confirm"])); 
        $code = $_POST["code"];
        if($user == "" || $psw == "" || $psw_confirm == "")  
        {  
            echo "<script>alert('请确认信息完整性!'); history.go(-1);</script>";  
        }
        else if($code != $_SESSION[' ver_code']){
            echo "<script>alert('验证码不正确,请重新输入!'); history.go(-1);</script>";
        }  
        else   
        {  
            if($psw == $psw_confirm)  
            {  
                $conn = mysqli_connect("localhost","root","root");   //连接数据库,帐号密码为自己数据库的帐号密码  
                if(mysqli_errno($conn)){
                    echo mysqli_error($conn);
                    exit;
                }
                mysqli_select_db($conn,"userdb");  //选择数据库  
                mysqli_set_charset($conn,'utf8'); //设定字符集  
                $sql = "select username from user where username = '$user'"; //SQL语句
                $result = mysqli_query($conn,$sql);    //执行SQL语句  
                $num = mysqli_num_rows($result); //统计执行结果影响的行数  

                if($num)    //如果已经存在该用户  
                {  
                    echo "<script>alert('用户名已存在'); history.go(-1);</script>";  
                }  
                else    //不存在当前注册用户名称  
                {   
                    $ip=ip2long($_SERVER['REMOTE_ADDR']); // 把ip地址转换成整型
                    $time=time();
                    $sql_insert = "insert into `user` (`username`,`userpwd`,`createtime`,`createip`) values('" . $user . "','" . $psw ."','".$time."','".$ip."')"; 
                    $res_insert = mysqli_query($conn,$sql_insert);  
                    if($res_insert)  
                    {  
                        echo "<script>alert('注册成功!');window.location.href='login.php';</script>";  
                    }  
                    else  
                    {  
                        echo "<script>alert('系统繁忙,请稍候!'); history.go(-1);</script>";  
                    }  
                }  
            }  
            else  
            {  
                echo "<script>alert('密码不一致!'); history.go(-1);</script>";  
            }  
        }  
    }  
    else  
    {  
        echo "<script>alert('提交未成功!');</script>";  
    }  
?>

代码解释:

  • 当在注册页面点击注册时进入注册处理页面

  • 判断post方式传过来的$_POST["hidden"]是否存在,不存在则提示提交未成功,返回注册界面,存在则继续。

  • 将传过来的值获取到(利用trim()函数过滤空白字符,密码使用md5()函数加密),然后判断是否为空,为空则弹出提示,返回注册界面,不为空则继续

  • 判断post方式传递过来的验证码值与之前存在session里面的验证码值是否相等,不相等则提示验证码不正确,返回注册页面,相等则继续执行

  • 判断传过来的密码和确认密码是否相等,不相等则提示密码不一致,相等则继续

  • 连接数据库、选择我们创建的数据库、设定字符集、通过用户名查询数据库,有结果则提示用户名存在,返回注册页面,没有结果则执行数据库插入语句,插入数据(插入数据库的字段增加了注册时间以及注册是使用的ip号)

  • 通过插入语句的返回值,判断是否插入成功,不成功则返回注册页面重新注册,成功则提示注册成功,跳转至登录页面

php用户注册登录系统之登录处理页面

登录处理页面

流程图如下:

第二版登录.png

代码如下:

<?php
session_start();
//登录处理界面 logincheck.php
//判断是否按下提交按钮
    if(isset($_POST["hidden"]) && $_POST["hidden"] == "hidden")  
    {  
    //将用户名和密码存入变量中,供后续使用
        $user = trim($_POST["username"]);//trim()函数移除字符串两侧的空白字符
        $psw = md5(trim($_POST["userpwd"]));//密码使用md5()加密一次,存入数据库
        $code = $_POST["code"];
        if($user == "" || $psw == "")  
        {
        //用户名或者密码其中之一为空,则弹出对话框,确定后返回当前页的上一页  
            echo "<script>alert('请输入用户名或者密码!'); history.go(-1);</script>";  
        }else if($code != $_SESSION[' ver_code']){
            echo "<script>alert('验证码不正确,请重新输入!'); history.go(-1);</script>";
        }  
        else  
        {  //确认用户名密码验证码不为空,则连接数据库
            $conn = mysqli_connect("localhost","root","root");//数据库帐号密码为安装数据库时设置
             if(mysqli_errno($conn)){
                echo mysqli_errno($conn);
                exit;
             }
            mysqli_select_db($conn,"userdb");  
            mysqli_set_charset($conn,'utf8'); 
            $sql = "select username,userpwd from user where username = '$user' and userpwd = '$psw'";  
            $result = mysqli_query($conn,$sql);  
            $num = mysqli_num_rows($result);  
            if($num)  
            {  
                echo "<script>alert('成功登录'); window.location.href='index.php';</script>";  
            }  
            else  
            {  
                echo "<script>alert('用户名或密码不正确!');history.go(-1);</script>";  
            }  
        }  
    }  
    else  
    {  
        echo "<script>alert('提交未成功!');</script>";  
    }  

?>

代码解释:

  • 当在登录页面点击登录时进入登录处理页面

  • 判断post方式传过来的$_POST["hidden"]是否存在,不存在则提示提交未成功,返回登录界面,存在则继续。

  • 将传过来的值获取到(利用trim()函数过滤空白字符,密码使用md5()函数加密),然后判断是否为空,为空则弹出提示,返回登录界面,不为空则继续

  • 判断post方式传递过来的验证码值与之前存在session里面的验证码值是否相等,不相等则提示验证码不正确,返回登录页面,相等则继续执行

  • 连接数据库、选择我们创建的数据库、设定字符集、通过用户名和密码查询数据库,判断用户名和密码是否存在于数据库,不存在则提示用户名或密码不正确,返回登录页面,存在则提示成功登录,跳转至首页

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,061评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,711评论 2 59
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,651评论 18 139
  • 1.种子。 beijing-wubajizhong_bjjzbk-rent seeds all dev
    iA_Ai阅读 450评论 0 0
  • 红尘之中秋风愁 花开花落流水去 缘来重始心头雨 诗舞枝端又一春
    凌峰峰行阅读 438评论 0 2