选择显示字体大小

php 用户认证


在专门 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() 来处理编码。

在一切都配置好了之后,连接时就会在浏览器出现查核密码的窗口,如上图就是 see.net 的 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 系统。

准备好 mysqlphp 之后,先在 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
//---------------------------
// 用户认证函数 auth.inc
// author: wilson peng
// copyright (c) 1999
//---------------------------
&#36;error401 = "/home/phpdocs/error/401.php" ;
if ( &#36;php_auth_pw == "" ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
} else {

&#36;db_id = mysql_pconnect ( "localhost" , "myid" , "mypw" );
&#36;result = mysql_db_query ( "mymember" , "select password, enable from memberauth where username='&#36;php_auth_user'" );

&#36;row = mysql_fetch_array ( &#36;result );
&#36;memberpasswd = &#36;row [ 0 ];
&#36;memberenable = &#36;row [ 1 ];
if ( &#36;memberenable == 0 ) {
echo "您的帐号被停用了" ;
exit;
}

if ( &#36;php_auth_pw != &#36;memberpasswd ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
}
}
?>
copyright (c) 1999, wilson peng

要使用这个 auth.inc,要在每个 php 的第一行加入
<? require( "auth.inc" ); ?> 。在加入本程序的 php 文件都会检查帐号密码,图片等就不会检查,比起使用 web 服务器功能的某目录下全都检查,php 显得有弹性多了。

&#36;error401 = "/home/phpdocs/error/401.php" ;

这行表示在用户按下取消,或检查失败时,要显示给用户看的文件。

if ( &#36;php_auth_pw == "" ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
} else {

到 else 之前,若没有传入密码,则送出输入密码的窗口。其中的 &#36;php_auth_user、&#36;php_auth_pw 是 php 中特殊的变量,分别代表用户确认的帐号及密码。上面的程序也是利用这两个变量来处理用户认证。

&#36;db_id = mysql_pconnect ( "localhost" , "myid" , "mypw" );
&#36;result = mysql_db_query ( "mymember" , "select password, enable from memberauth where username='&#36;php_auth_user'" );

&#36;row = mysql_fetch_array ( &#36;result );
&#36;memberpasswd = &#36;row [ 0 ];
&#36;memberenable = &#36;row [ 1 ];

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

if ( &#36;memberenable == 0 ) {
echo "您的帐号被停用了" ;
exit;
}

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

if ( &#36;php_auth_pw != &#36;memberpasswd ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
}

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

在实际使用时,可以视需要加入的网页再加入 auth.inc 这个文件,就不用连看张图形也要查一次密码,轿募服务器和用户二端的资源。当然,和 mysql 的连系上,可以使用 mysql_pconnect() 一直和 mysql 服务器连接。或是使用 mysql_connect() 每次重新连接,用这个函数要记得早点使用 mysql_close() 将数据库关闭。下面的程序 auth1.inc 是另一版本的认证程序,就是打开连接后马上关闭,释放资源的例子。

<?php
//---------------------------
// 用户认证函数-1 auth1.inc
// author: wilson peng
// copyright (c) 1999
//---------------------------
&#36;error401 = "/home/phpdocs/error/401.php" ;
if ( &#36;php_auth_pw == "" ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
} else {

&#36;db_id = mysql_connect ( "localhost" , "myid" , "mypw" );
&#36;result = mysql_db_query ( "mymember" , "select password, enable from memberauth where username='&#36;php_auth_user'" );

&#36;row = mysql_fetch_array ( &#36;result );
&#36;memberpasswd = &#36;row [ 0 ];
&#36;memberenable = &#36;row [ 1 ];
mysql_close ( &#36;db_id );
if ( &#36;memberenable == 0 ) {
echo "您的帐号被停用了" ;
exit;
}

if ( &#36;php_auth_pw != &#36;memberpasswd ) {
header ( "www-authenticate: basic realm=\"超金卡会员\"" );
header ( "http/1.0 401 unauthorized" );
include( &#36;error401 );
exit;
}
}
?>
copyright (c) 1999, wilson peng

在实际应用时,可以在数据库中加入更多功能,如用户分组 (cug) 的功能;或是加入时间字段,可做到期检查。其中的变化,端赖设计者的巧思了。

  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons