PHP+APACHE實作使用者驗證的方法

PHP中文网
發布: 2016-08-08 09:34:10
原創
1364 人瀏覽過

               在專業的 Web 站台上,常常需要使用者的帳號及密碼,也就是身分確認的動作。早期的 NCSA httpd 服務器並沒有提供這項使用者確認的功能,Webmaster 只能用手工打造一個身分確認的 CGI 程式。  
自 CERN httpd 之後的 Web 服務器大部分都提供了使用者身分確認的功能。僅管每套 Web 服務器的設定都不太相同,但在設定上都大同小異。  

以下就是 Apache 伺服器上的使用者身分確認的設定。  

<Directory /home/MyMember> 
AuthType Basic 
AuthName MyMember 
AuthUserFile /usr/local/MyMember.txt 
Options Includes ExecCGI 
<Limit GET POST> 
require valid-user 
</Limit> 
</Directory>
登入後複製


 

在這個範例中,當使用者在看 MyMember 目錄下所有的檔案,包括圖片檔案及其它各式檔案時,都需要使用者的帳號密碼確認。而使用者的帳號及密碼檔都存在於/usr/local/MyMember.txt 之中。  

這個帳號密碼檔 /usr/local/MyMember.txt 的樣子可能如下例。其中冒號前面的字串是使用者帳號,冒號之後的字串是經過不可還原加密的密碼,編碼一般都是使用傳統的DES 編碼,密碼的頭二個字是類似種子的字符(salt),本例中都是3P。每行代表一位使用者。當然 Webmaster 要自行控制重覆帳號的情形。比較特殊是在 Win32 系統上架 Apache 的情形,冒號後的密碼不可加密,因為 Win32 沒有提供這方面的編碼  
API,因此使用者密碼以明碼的方式存在。  

john1234:3PWudBlJMiwro  
queenwan:3PFNVLNPN9W0M  
noname00:3PEsXaJx5pk7E  
wilson49:3PjoWb0EnaG22  
rootboot:3PIt0snI6.84E  
sun_moon:3PvymMeNOc.x.  
nobody38:3PbskPKwV94hw
登入後複製

在 Apache 1.3.6 版上,可以用 ~apache/bin/htpasswd 來產生單筆的帳號及密碼,但對於需要大筆資料的商業站台,可能就需要自行寫程式來處理了。 UNIX 上需要呼叫 crypt() 來處理編碼。  



在一切都設定好了之後,連線時就會在瀏覽器出現核對密碼的視窗,如上圖就是SEEDNet 的 MySEED 網站的使用者核對機制。在輸入了帳號及密碼後,瀏覽器會將它用BASE64 編碼後,傳到伺服器端。當然BASE64 只是編碼不是加密,因此在網路上這種傳輸的安全性仍然不高,還是有可能被中間的劊客截下,再將BASE64 還原,這也是整個用戶認證中最美中不足的地方,或許日後支援摘要認證(Digest) 及使用md5 編碼後,可以解決此問題。之後每一頁仍然需要帳號及密碼,只不過瀏覽器會幫你主動送出,不用再輸入帳號密碼了。這方面瀏覽器會保留到關閉為止,下次重執行瀏覽器仍需輸入第一次。  

在使用者數量少時,使用上述的方法輕鬆又省事。但在使用者有數萬人,甚至數十萬人時,會發生整個伺服器的效率都被搜尋帳號密碼下拖垮,可能讀取一頁需要數十秒到數分鐘。這種情形再使用伺服器提供的密碼查核機制就不太明智了。在Netscape EnterPRise Server 上可能就可以使用 NSAPI 來開發自己的核對方式,在IIS 上也可以用 ISAPI 過濾器開發。寫 C/C++ 程式呼叫 NSAPI/ISAPI 總是很累,在php 上有了另外的選擇,這也是本節的主題。  


PHP 的 HTTP 相關函式庫提供了 header() 的函數。許多 Web 伺服器與客戶端的互動,都可以使用這個函數來變戲法。例如在某個 PHP 頁面最開始處,也就是第一行或第二行,加入以下的程序,可以將使用者重導到作者的網頁。  


<?php  
header("Location: http://wilson.gs");  
exit;  
?>
登入後複製


當然,在上述程式之後的 HTML 文字或是 PHP 程式都永遠不會出現在使用者端了。  

同樣的道理,我們就用 header() 來變成使用者認證的把戲。可以在 PHP 的最開頭送出字符串到使用者端,就會在使用者端出現下圖的視窗。  


<?php  
Header("WWW-Authenticate: Basic realm="Member"");  
Header("HTTP/1.0 401 Unauthorized");  
?>
登入後複製

在程式中字串 realm="Member" 中的 Member 字样出现在图中,当然若使用中文字取代,浏览器端也会出现中文字,如上面的 MySEED 图。若 Web 站台使用者还有其它语文,如英文或日文,送出中文的 realm 字串似乎就比较不合适。无论如何,这都要视站台的性质及使用者定位而决定。

当然这还是很粗糙,因为除了送出视窗后,就没有下文了,帐号输入正确也好,输入错误也罢,都不会有任何的结果。我们需要再更进阶的程式来处理。


在后端的使用认证上,考虑使用资料库作为储存帐号及密码的后端,在这种架构可以容纳许多的使用者,管它一万个使用者还是十万个使用者。若您的站已有数十万个使用者帐号,那么恭喜您,您的站算是世界级的大站了。MySQL 是个不错的选择,许多站台,甚至是商业化的站台都用它来做后端的资料库。当然您要架真正的商业站台,钱不是问题的话,那可以使用口碑最广的 Oracle 资料库系列。

要在 PHP 中使用任何资料库,都要先将资料库的伺服器端及客户端设定好,之后才编译 PHP 及 Apache 系统。

准备好 MySQL 及 PHP 之后,先在 MySQL 中加入新的资料库,本例是加入mymember,用别的名字当然也可以。MySQL 要加入资料库 (Database) 很容易,只要在MySQL 存放 Database 的地方 mkdir 就可以了。例如在 UNIX Shell 下打

hahaha:/usr/local/mysql/data# mkdir mymember
登入後複製

在建立了资料库之后,尚需要建立资料表格 (Table) 方能使用。设定的表格如下,可以将它储在 /tmp/memberauth.sql 中

CREATE TABLE MemberAuth (  
Serial mediumint(9) NOT NULL auto_increment,  
Username char(8) NOT NULL,  
PassWord char(8) NOT NULL,  
Enable char(1) DEFAULT ’0’ NOT NULL,  
PRIMARY KEY (Serial)  
);
登入後複製

档案 memberauth.sql

先看看 memberauth.sql 的这些栏位。Serial 是个自动增加的整数栏位,每输入一笔资料,就会自动加一,这当然不能是空的栏位,于是就用 NOT NULL 了。第二个栏位是 Username,代表使用者的帐号,为了统一以及适应各系统起见,设定成八个字,当然这个栏位也不能是空的。Password 是第三个栏位,为使用者的密码。第四个栏位 Enable 做为帐号是否有效的旗标,设计上 0 表示无用,1 表可用,日后还可加入其它值做不同的用途。

设计好了资料表之后,就要将资料表加入资料库了。由于常要使用 MySQL 资料库,可以到 http://www.phpwizard.net/phpMyAdmin 下载 phpMyAdmin,使用浏览器操作及管理 MySQL,轻松又方便。若使用这套 phpMyAdmin 可以在它的使用者介面上输入memberauth.sql 加入 MySQL 中。或者也可以在 UNIX Shell 下输入下式,也是有同样的效果。

mysql mymember < /tmp/memberauth.sql
登入後複製

在准备好了之后,就可以输入使用者帐号及密码在 memberauth 资料表中了。当然还是使用 phpMyAdmin 方便,用 mysql 程式就要一笔笔的 INSERT 了。

接着进入了设计函式的阶段了。


<?php  
file://---------------------------  
// 使用者认证函式 auth.inc  
// Author: Wilson Peng  
// Copyright (C) 1999  
file://---------------------------  
$error401 = "/home/phpdocs/error/401.php";  
if ($PHP_AUTH_PW=="") {  
Header("WWW-Authenticate: Basic realm="超金卡会员"");  
Header("HTTP/1.0 401 Unauthorized");  
include($error401);  
exit;  
} else {  
$db_id = mysql_pconnect("localhost", "myid", "mypw");  
$result = mysql_db_query("mymember","select password, enable  
from MemberAuth where username=’$PHP_AUTH_USER’");  
$row = mysql_fetch_array($result);  
$MemberPasswd = $row[0];  
$MemberEnable = $row[1];  
if ($MemberEnable==0) {  
echo "您的帐号被停用了";  
exit;  
}  
if ($PHP_AUTH_PW!=$MemberPasswd) {  
Header("WWW-Authenticate: Basic realm="超金卡会员"");  
Header("HTTP/1.0 401 Unauthorized");  
include($error401);  
exit;  
}  
}  
?>
登入後複製

Copyright (C) 1999, Wilson Peng

要使用这个 auth.inc,要在每个 PHP 的第一行加入

<? require("auth.inc"); ?> 。
登入後複製

在加入本程式的 PHP 档案都会检查帐号密码,图片等就不会检查,比起使用 Web 伺服器功能的某目录下全都检查,PHP 显得有弹性多了。

$error401 = "/home/phpdocs/error/401.php";
登入後複製

这行表示在使用者按下取消,或检查失败时,要显示给使用者看的档案。

if ($PHP_AUTH_PW=="") { 
Header("WWW-Authenticate: Basic realm="超金卡会员""); 
Header("HTTP/1.0 401 Unauthorized"); 
include($error401); 
exit; 
} else
登入後複製

到 else 之前,若没有传入密码,则送出输入密码的视窗。其中的
$PHP_AUTH_USER、$PHP_AUTH_PW 是 PHP 中特殊的变数,分别代表使用者确认的帐号及密码。上面的程式也是利用这二个变数来处理使用者认证。

$db_id = mysql_pconnect("localhost", "myid", "mypw"); 
$result = mysql_db_query("mymember","select password, enable from 
MemberAuth where username=’$PHP_AUTH_USER’"); 

$row = mysql_fetch_array($result); 
$MemberPasswd = $row[0]; 
$MemberEnable = $row[1];
登入後複製

若使用者有输入帐号及密码,则向资料库查询。同时查核该使用者是否仍可使用。

if ($MemberEnable==0) { 
echo "您的帐号被停用了"; 
exit; 
}
登入後複製

上四行程式为帐号被停用的情形。

if ($PHP_AUTH_PW!=$MemberPasswd) { 
Header("WWW-Authenticate: Basic realm="超金卡会员""); 
Header("HTTP/1.0 401 Unauthorized"); 
include($error401); 
exit; 
}
登入後複製

密码错误则再次向使用者要求输入帐号及密码。

在实际使用时,可以视需要加入的网页再加入 auth.inc 这个档案,就不用连看张图形也要查一次密码,降低伺服器和使用者二端的资源。当然,和 MySQL 的连系上,可以使用 mysql_pconnect() 一直和 MySQL 伺服器连线。或是使用mysql_connect() 每次重新连线,用这个函式要记得早点使用 mysql_close() 将资料库关闭。下面的程式 auth1.inc 是另一版本的认证程式,就是开启连线后马上关闭,释放资源的例子。

登入後複製

以上就是PHP+APACHE实现用户验证的方法的内容,更多相关内容请关注PHP中文网(www.php.cn)!


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板