首页 » PHP和MySQL Web开发(原书第4版) » PHP和MySQL Web开发(原书第4版)全文在线阅读

《PHP和MySQL Web开发(原书第4版)》27.5 实现用户身份验证

关灯直达底部

用户身份验证模块包括4个主要的元素:用户注册、登录和登出、修改密码以及重置密码。我们将按顺序详细讨论每个元素。

27.5.1 注册用户

要注册一个用户,需要通过一个表单获得用户的详细信息,并且将这些信息保存到数据库中。

当用户点击login.php页面上的/"Not a member?/"链接时,就会出现一个由register_form.php产生的注册表单。该脚本如程序清单27-5所示。

程序清单27-5 register_form.php——该表单让用户在PHPbookmark系统中注册

<?php

require_once(/'bookmark_fns.php/');

do_html_header(/'User Registration/');

display_registration_form;

do_html_footer;

?>

可以看到,该页非常简单,只调用了来自output_fns.php的输出库中的函数。该脚本输出如图27-4所示。

图 27-4 注册表单获取了数据库需要的用户详细信息。密码要求输入两次,以防输入错误

该页中的灰色表单是由display_registration_form函数输出的,该函数也包含在output_fns.php中。当用户点击/"Register/"按钮时,register_new.php脚本将运行。该脚本如程序清单27-6所示。

程序清单27-6 register_new.php——该脚本验证新用户的数据,并将其存入数据库

<?php

//include function files for this application

require_once(/'bookmark_fns.php/');

//create short variable names

$email=$_POST[/'email/'];

$username=$_POST[/'username/'];

$passwd=$_POST[/'passwd/'];

$passwd2=$_POST[/'passwd2/'];

//start session which may be needed later

//start it now because it must go before headers

session_start;

try{

//check forms filled in

if(!filled_out($_POST)){

throw new Exception(/'You have not filled the form out correctly-

please go back and try again./');

}

//email address not valid

if(!valid_email($email)){

throw new Exception(/'That is not a valid email address.

Please go back and try again./');

}

//passwords not the same

if($passwd!=$passwd2){

throw new Exception(/'The passwords you entered do not match-

please go back and try again./');

}

//check password length is ok

//ok if username truncates,but passwords will get

//munged if they are too long.

if((strlen($passwd)<6)||(strlen($passwd)>16)){

throw new Exception(/'Your password must be between 6 and 16 characters.

Please go back and try again./');

}

//attempt to register

//this function can also throw an exception

register($username,$email,$passwd);

//register session variable

$_SESSION[/'valid_user/']=$username;

//provide link to members page

do_html_header(/'Registration successful/');

echo/'Your registration was successful.Go to the members page to start

setting up your bookmarks!/';

do_html_url(/'member.php/',/'Go to members page/');

//end page

do_html_footer;

}

catch(Exception$e){

do_html_header(/'Problem:/');

echo$e->getMessage;

do_html_footer;

exit;

}

?>

这是该项目中我们看到的第一个比较复杂的脚本。该脚本的起始部分包含了应用程序函数文件并启动了一个会话(用户注册的时候,我们将他的用户名创建为会话变量,正如我们在第23章中“在PHP中使用会话控制”所介绍的那样)。

脚本的主体有一个try语句块,因为需要检查许多条件。如果任何一个条件失败,执行将进入catch语句块,我们将在稍后详细介绍。

接下来验证用户输入的数据。在此过程中,我们要测试许多条件,如下所示。

■检查表单是否完全填写。调用filled_out函数测试,如下所示:

if(!filled_out($_POST))

这个函数是我们自己编写的函数之一。它位于data_valid_fns.php函数库。稍后,我们将详细介绍这个函数。

■检查邮件地址是否有效。测试如下所示:

if(valid_email($email))

这个函数也是我们自己编写的函数之一。它也位于data_valid_fns.php函数库。

■验证用户两次输入的密码是否一致,如下所示:

if($passwd!=$passwd2)

■验证密码长度是否在规定范围之内,如下所示:

if((strlen($passwd)<6)

if((strlen($passwd)>16)

在我们的例子中,密码至少为6个字符,这样以防别人容易猜出,同时用户名要少于17个字符,以适合存放到数据库中。请注意,密码的最大长度并不局限于此,因为它是以SHA1哈希值保存的,因此通常是40个字符,而不受密码长度的限制。

本例用到的数据验证函数filled_out和valid_email,分别如程序清单27-7和程序清单27-8所示。

程序清单27-7 data_valid_fns.php文件中的filled_out函数——该函数检查表单是否完全填写

function filled_out($form_vars){

//test that each variable has a value

foreach($form_vars as$key=>$value){

if((!isset($key))||($value==/'/')){

return false;

}

}

return true;

}

程序清单27-8 data_valid_fns.php文件中的valid_email函数——该函数检查邮件地址是否有效

function valid_email($address){

//check an email address is possibly valid

if(ereg(/'^[a-zA-Z0-9_.-][email protected][a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/',$address)){

return true;

}else{

return false;

}

}

函数filled_out需要传递一个数组变量,通常是$_POST或$_GET变量数组。它检查表单是否完全填写,如果完全填写则返回true,否则返回false。

valid_email函数使用了在第4章“字符串操作与正则表达式”中介绍的正则表达式来验证邮件地址。如果地址是有效的,就返回true,否则返回false。

在验证了输入数据之后,我们就可以尝试注册该用户了。如果回头看看程序清单27-6,会发现我们是按如下方式实现的:

register($username,$email,$passwd);

//register session variable

$_SESSION[/'valid_user/']=$username;

//provide link to members page

do_html_header(/'Registration successful/');

echo/'Your registration was successful.Go to the members page to start

setting up your bookmarks!/';

do_html_url(/'member.php/',/'Go to members page/');

//end page

do_html_footer;

可以看到,我们使用用户输入的用户名、邮件地址和密码作为参数调用了register函数。如果函数执行成功,我们就将用户名注册为会话变量,并为用户提供一个指向成员主页的链接(如果函数执行失败,它将抛出一个可以在catch语句块中捕获的异常)。其输出如图27-5所示。

图 27-5 注册成功,用户可以访问成员页

register函数包含在user_auth_fns.php函数库中。函数代码如程序清单27-9所示。

程序清单27-9 user_auth_fns.php文件中的register函数——该函数试图将用户信息提交到数据库

function register($username,$email,$password){

//register new person with db

//return true or error message

//connect to db

$conn=db_connect;

//check if username is unique

$result=$conn->query(/"select*from user where username=/'/".$username./"/'/");

if(!$result){

throw new Exception(/'Could not execute query/');

}

if($result->num_rows>0){

throw new Exception(/'That username is taken-go back and choose another

one./');

}

//if ok,put in db

$result=$conn->query(/"insert into user values

(/'/".$username./"/',sha1(/'/".$password./"/'),/'/".$email./"/')/");

if(!$result){

throw new Exception(/'Could not register you in database-please try again

later./');

}

return true;

}

在这个函数中,也没有特别新的内容,只是将它连接到前面已经建立的数据库中。如果选定的用户名已经存在,或者数据库不能被更新,它将抛出一个异常。否则,它将更新数据库并返回true。

需要注意的是,我们使用了自己编写的函数db_connect来执行数据库连接操作。该函数只提供了一个连接到数据库的地址,而该地址同时还保存着用户名和密码。这样,如果要修改数据库中的密码,只需改变应用程序中的一个文件即可。db_connect函数如程序清单27-10所示。

程序清单27-10 db_fns.php文件中的db_connect函数——该函数连接MySQL数据库

<?php

function db_connect{

$result=new mysqli(/'localhost/',/'bm_user/',/'password/',/'bookmarks/');

if(!$result){

throw new Exception(/'Could not connect to database server/');

}else{

return$result;

}

}

?>

在用户注册之后,可以通过正规的登录或登出页面登录和退出网站。接下来,我们就将实现它。