php基于表单密码验证与HTTP验证用法实例
本文实例讲述了php基于表单密码验证与HTTP验证用法。分享给大家供大家参考。具体分析如下:
PHP的HTTP认证机制仅在PHP以Apache模块方式运行时才有效,因此该功能不适用于CGI版本。在Apache模块的PHP脚本中,可以用header()函数来向客户端浏览器发送“AuthenticationRequired”信息,使其弹出一个用户名/密码输入窗口。当用户输入用户名和密码后,包含有URL的PHP脚本将会加上预定义变量PHP_AUTH_USER,PHP_AUTH_PW和AUTH_TYPE被再次调用,这三个变量分别被设定为用户名,密码和认证类型。预定义变量保存在$_SERVER或者$HTTP_SERVER_VARS数组中。支持“Basic”和“Digest”(自PHP5.1.0起)认证方法。感兴趣的朋友可以参阅header()函数相关信息。
PHP版本问题:Autoglobals全局变量,包括$_SERVER等,自PHP4.1.0起有效,$HTTP_SERVER_VARS从PHP3开始有效。
以下是在页面上强迫客户端认证的脚本范例.
例子34-1.BasicHTTP认证范例
<?php if(!isset($_SERVER['PHP_AUTH_USER'])){ header('WWW-Authenticate:Basicrealm="MyRealm"'); header('HTTP/1.0401Unauthorized'); echo'TexttosendifuserhitsCancelbutton'; exit; }else{ echo"<p>Hello{$_SERVER['PHP_AUTH_USER']}.</p>"; echo"<p>Youentered{$_SERVER['PHP_AUTH_PW']}asyourpassword.</p>"; } ?>
例子34-2.DigestHTTP认证范例
本例演示怎样实现一个简单的DigestHTTP认证脚本,更多信息请参考RFC2617.
<?php $realm='Restrictedarea'; //user=>password $users=array('admin'=>'mypass','guest'=>'guest'); if(!isset($_SERVER['PHP_AUTH_DIGEST'])){ header('HTTP/1.1401Unauthorized'); header('WWW-Authenticate:Digestrealm="'.$realm. '"qop="auth"nonce="'.uniqid().'"opaque="'.md5($realm).'"'); die('TexttosendifuserhitsCancelbutton'); } //analizethePHP_AUTH_DIGESTvariable preg_match('/username="(?P<username>.*)",s*realm="(?P<realm>.*)",s*nonce="(?P<nonce>.*)",s*uri="(?P<uri>.*)",s*response="(?P<response>.*)",s*opaque="(?P<opaque>.*)",s*qop=(?P<qop>.*),s*nc=(?P<nc>.*),s*cnonce="(?P<cnonce>.*)"/',$_SERVER['PHP_AUTH_DIGEST'],$digest); if(!isset($users[$digest['username']])) die('Usernamenotvalid!'); //generatethevalidresponse $A1=md5($digest['username'].':'.$realm.':'.$users[$digest['username']]); $A2=md5($_SERVER['REQUEST_METHOD'].':'.$digest['uri']); $valid_response=md5($A1.':'.$digest['nonce'].':'.$digest['nc'].':'.$digest['cnonce'].':'.$digest['qop'].':'.$A2); if($digest['response']!=$valid_response) die('WrongCredentials!'); //ok,validusername&password echo'Yourareloggedinas:'.$digest['username']; ?>
兼容性问题:在编写HTTP标头代码时请格外小心,为了对所有的客户端保证兼容性,关键字“Basic”的第一个字母必须大写为“B”,分界字符串必须用双引号(不是单引号)引用;并且在标头行HTTP/1.0401中,在401前必须有且仅有一个空格.
在以上例子中,仅仅只打印出了PHP_AUTH_USER和PHP_AUTH_PW的值,但在实际运用中,可能需要对用户名和密码的合法性进行检查,或许进行数据库教程的查询,或许从dbm文件中检索.
注意有些InternetExplorer浏览器本身有问题。它对标头的顺序显得似乎有点吹毛求疵。目前看来在发送HTTP/1.0401之前先发送WWW-Authenticate标头似乎可以解决此问题。
自PHP4.3.0起,为了防止有人通过编写脚本来从用传统外部机制认证的页面上获取密码,当外部认证对特定页面有效,并且安全模式被开启时,PHP_AUTH变量将不会被设置,但无论如何,REMOTE_USER可以被用来辨认外部认证的用户,因此可以用$_SERVER['REMOTE_USER']变量.
配置说明:PHP用是否有AuthType指令来判断外部认证机制是否有效。
注意,这仍然不能防止有人通过未认证的URL来从同一服务器上认证的URL上偷取密码.
NetscapeNavigator和InternetExplorer浏览器都会在收到401的服务端返回信息时清空所有的本地浏览器整个域的Windows认证缓存,这能够有效的注销一个用户,并迫使他们重新输入他们的用户名和密码,有些人用这种方法来使登录状态“过期”,或者作为“注销”按钮的响应行为.
例子34-3.强迫重新输入用户名和密码的HTTP认证的范例
<?php functionauthenticate(){ header('WWW-Authenticate:Basicrealm="TestAuthenticationSystem"'); header('HTTP/1.0401Unauthorized'); echo"YoumustenteravalidloginIDandpasswordtoaccessthisresourcen"; exit; } if(!isset($_SERVER['PHP_AUTH_USER'])|| ($_POST['SeenBefore']==1&&$_POST['OldAuth']==$_SERVER['PHP_AUTH_USER'])){ authenticate(); } else{ echo"<p>Welcome:{$_SERVER['PHP_AUTH_USER']}<br/>"; echo"Old:{$_REQUEST['OldAuth']}"; echo"<formaction='{$_SERVER['PHP_SELF']}'METHOD='post'>n"; echo"<inputtype='hidden'name='SeenBefore'value='1'/>n"; echo"<inputtype='hidden'name='OldAuth'value='{$_SERVER['PHP_AUTH_USER']}'/>n"; echo"<inputtype='submit'value='ReAuthenticate'/>n"; echo"</form></p>n"; } ?>
该行为对于HTTP的Basic认证标准来说并不是必须的,因此不能依靠这种方法,对Lynx浏览器的测试表明Lynx在收到401的服务端返回信息时不会清空认证文件,因此只要对认证文件的检查要求没有变化,只要用户点击“后退”按钮,再点击“前进”按钮,其原有资源仍然能够被访问,不过,用户可以通过按“_”键来清空他们的认证信息.
在下例中,我们是使用$PHP_AUTH_USER和$PHP_AUTH_PW这两个变量来验证进入者是否合法并允许进入。在本例中被允许登录的用户名称和密码对分别为tnc和nature:
<?php if(!isset($PHP_AUTH_USER)) { Header("WWW-Authenticate:Basicrealm="MyRealm""); Header("HTTP/1.0401Unauthorized"); echo"TexttosendifuserhitsCancelbuttonn"; exit; } else { if(!($PHP_AUTH_USER=="tnc"&&$PHP_AUTH_PW=="nature")) { //如果是错误的用户名称/密码对,强制再验证 Header("WWW-Authenticate:Basicrealm="MyRealm""); Header("HTTP/1.0401Unauthorized"); echo"ERROR:$PHP_AUTH_USER/$PHP_AUTH_PWisinvalid."; exit; } else { echo"Welcometnc!"; } ?>
事实上再实际引用中不大可能如上面使用代码段明显的用户名称/密码对,而是利用数据库或者加密的密码文件存取它们.
根据指定的验证信息核实用户身份:
首先,我们可以使用以下代码确定用户是否已经输入了用户名和密码,并显示出用户输入的信息.
<?php if(!isset($PHP_AUTH_USER)){ header('WWW-Authenticate:Basicrealm="MyPrivateStuff"'); header('HTTP/1.0401Unauthorized'); echo'AuthorizationRequired.'; exit; } else{ echo"<P>Youhaveenteredthisusername:$PHP_AUTH_USER<br> Youhaveenteredthispassword:$PHP_AUTH_PW<br> Theauthorizationtypeis:$PHP_AUTH_TYPE</p>"; } ?>
说明:
isset()函数用于确定某个变量是否已被赋值,根据变量值是否存在,返回true或false.
header()函数用于发送特定的HTTP标头,注意,使用header()函数时,一定要在任何产生实际输出的HTML或PHP代码前面调用该函数.
虽然上述代码相当简单,没有根据任何实际值对用户输入的用户名和密码进行有效验证,但是至少我们了解了如何使用PHP在客户端产生输入对话框.
下面,我们就来了解一下如何根据指定的验证信息核实用户身份,代码如下:
<?php if(!isset($PHP_AUTH_USER)){ header('WWW-Authenticate:Basicrealm="MyPrivateStuff"'); header('HTTP/1.0401Unauthorized'); echo'AuthorizationRequired.'; exit; } elseif(isset($PHP_AUTH_USER)){ if(($PHP_AUTH_USER!="admin")||($PHP_AUTH_PW!="123")){ header('WWW-Authenticate:Basicrealm="MyPrivateStuff"'); header('HTTP/1.0401Unauthorized'); echo'AuthorizationRequired.'; exit; }else{ echo"<P>You'reauthorized!</p>"; } } ?>
在这里,我们首先检查用户是否已经输入了用户名称和密码,如果没有则弹出相应对话框要求用户输入身份信息,随后,我们通过判断用户输入的信息是否符合admin/123这一指定用户帐号来授予用户访问权限或提示用户再次输入正确的信息,这种方法适用于所有用户都使用同一登录帐号的网站.
另一种简易的密码验证
如果你是在windows98下面编写和运行着你的PHP脚本,或者是你在Linux下面按默认设置,将PHP安装成一个CGI程序的话,你将无法使用上面的PHP程序来实现验证功能,为此,无边给大家提供了另外一种简易的密码验证的方法,虽然实用性不大,但是拿来学习还是挺好的.
<?php if($_POST[Submit]=="提交"){ //如果用户提交了数据,则执行操作 $password=$_POST[password];//获取用户输入的数据,并保存在变量password中 $cpassword=$_POST[cpassword]; //获取用户输入的确认数据,保存在变量$cpassord中 if(emptyempty($password)||emptyempty($cpassword)) { die("密码不可空!"); } elseif(((strlen($password)<5)||(strlen($password)>15))) { die("密码长度在5和15之间"); } //---值比较 elseif(!(strlen($password)==strlen($cpassword))) { die("两次输入密码不匹配!"); } elseif(!($password===$cpassword))//值和数据类型比较 { die("两次密码不匹配!"); } else //循环输出密码,因为是密码所以输出*号 { for($i=0;$i<strlen($password);$i++) { echo"*"; } } } ?> <html> <head> <metahttp-equiv="Content-Type"content="text/html;charset=gb2312"> <title>表单验证-密码字段验证</title> </head> <body> <formname="form1"method="post"action="<?=$_SERVER['PHP_SELF']?>"> 请输入密码:<inputtype="text"name="password"><br> 确认密码:<inputtype="password"name="cpassword"><br> <inputtype="submit"name="Submit"value="提交"> </form> </body> </html>
希望本文所述对大家的php程序设计有所帮助。