韶华将逝,雄心未已;欲与众君,共习此技.

《PHP和MySQL Web开发》学习笔记(十八)

上一篇 / 下一篇  2007-09-28 11:13:56 / 天气: 晴朗 / 心情: 平静 / 个人分类:PHP & MySQL

第16章 使用PHP和MySQL实现身份验证
 
16.1 识别访问者
Web是一个匿名媒体,但是通常知道谁在访问网站是非常有意义的。如果没有访问者的帮助,很难了解他们的信息,这对于访问者的隐私来讲是有利的。但是通过一些操作,服务器就可以发现许多关于连接他们的计算机与网络的信息。
每一台连接到互联网的计算机有一个惟一的IP地址。根据访问者的IP地址,可以推测出他的一些信息。可以发现谁拥有该IP,有时甚至可以猜测出访问者的地理位置。
幸运的是,对于网络用户,他们的浏览器无法泄露可以识别他们身份的信息。如果要知道访问者的名字或者其他信息,必须亲自询问他。
如果已经从访问者那里询问和获得了信息,只需要在他下次访问的时候将这些信息与访问者联系起来。
通常,许多人可能会共享一台计算机,而且许多人还可能使用多台计算机。至少在一段时间之后,要再次询问访问者的名字。除了询问访问者的名字,可能还会要求访问者提供某种证据来证明身份。
 
16.2 实现访问控制
实现简单的访问控制并不困难。如下所示的代码(代码略)提供了一个简单的身份验证机制,它允许通过身份验证的用户浏览某个网页,但是它存在一些明显的问题:在脚本中只对一个用户名和密码进行了硬编码;将密码以普通文件形式保存;只保护一个页面;以普通文本形式传输密码。
 
16.2.1 保存密码
与将用户名和密码保存在脚本中相比,还有许多更好的用来保存用户名和密码的地方。将数据保存在服务器的另一个文件可以使我们能够轻松地编写一个用来添加和删除用户以及修改密码的程序。
在不至于严重影响脚本的的执行速度前提下,一个脚本或者其他数据文件内部能够保存的用户数量是有限的。正如前面所介绍的,如果考虑在一个文件中保存并查找大量的项目,应该考虑使用一个数据库来代替。如果要保存和搜索的内容多于100个项目,应该使用一个数据库而不是一个普通文件来实现,这是一条重要的规则。
使用数据库来保存用户名和密码将不会使脚本复杂很多,但是这将允许我们快速地验证不同用户的身份。它也允许我们轻松地编写一段脚本来添加新用户、删除用户并且允许用户修改自己的密码。

(代码略)
 
16.2.2 密码的加密
无论将数据保存在数据库中还是文件中,都没有必要冒险以普通文本格式存储密码。只要稍微做一点工作,就可以通过一种使用单向哈希的算法来提高密码的安全性。
PHP提供了许多单向的哈希函数。最早的也是安全性最低的是UNIX Crypt算法,它由crypt()函数实现。md5()函数实现的消息摘要5(Message Digest 5)算法更强大一些,而且可以在PHP的大多数版本使用。如果不要求与低版本的PHP兼容,可以使用加密的哈希算法(SHA-1)。
PHP的sha1()函数提供了一个功能强大的单向加密哈希函数。该函数原型如下所示:string sha1 (string str [, bool raw_output])
给定字符串str,该函数将返回一个40个字符的伪随机字符串。如果将raw_output参数设置为true,将得到一个20个字符的二进制字符串数据。例如,给定字符串"password",sha1()函数将返回如下所示的结果:"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"
这个字符串无法解密,即使是字符串的创建者也无法还原成"password"字符串,因此初看起来,这个函数的作用并不大。但是真正使得该函数功能强大的原因在于它的输出是确定的。
在对字符串使用sha1()函数之前,并不需要知道加密结果表示什么。我们只需要知道输入的密码是否与最初通过sha1()运行的结果密码相同。
如果要使用一个MySQL数据库来保存身份验证数据,可以使用PHP的sha1()函数,或者MySQL的SHA1()函数MySQL提供了比PHP更广泛的哈希算法,但是二者的作用都是相同的。
记记住,这个哈希函数通常将返回固定大小的数据。在SHA1这种情况下,它是用40个字符的字符串来表示。请确认数据库列具有这样的宽度。
 
16.2.3 保护多个网页
保护多个网页最简单的方法就是使用Web服务器提供的访问控制机制。
如果使用这种方法,当访问者进入网站后,网站会要求他们每浏览一页时都重新输入名字和密码,显然,这对访问者来说是难以接受的。
我们可以将他们输入的细节信息附加网页的每个超级链接中。由于用户可能输入在URL中不允许出现的空格或者其他字符,应用使用urlencode()函数对这些字符进行安全的编码。

尽管如何,该方法仍然会有一些问题。因为这些数据将包含在发送给用户的网页和他们访问的URL中,他们访问的受保护页可以被任何使用同一台计算机的人看见,这些人可以通过回退步骤看到以前的缓存页,或者通过查看浏览器的历史清单而浏览这些受保护页。因为我们在每页被请求或者发送时重复地发送密码到浏览器,这些敏感信息的传输频率更高。
现在,有两个很好的方法可以解决这些问题:HTTP基本身份验证和会话。基本身份验证克服了缓存问题,但是在每次请求时,浏览器仍然会将密码发送给服务器。会话控制技术克服了这两方面问题。
 
16.3 使用基本身份验证
幸运的是,验证用户只是一个非常常见的任务,因此HTTP内置有身份验证功能。脚本或Web服务器可以通过Web浏览器请求身份验证。Web浏览器负责显示一个对话框或类似设备,从而从用户那里获得所需的信息。
尽管Web服务器对每个用户请求都要求新的身份验证详细信息,但Web浏临器不必在每页中都要求用户输入详细信息。通常,浏览器可以保存这些详细信息,只要用户打开一个浏览器窗口,它就会自动地将这些所需的详细信息重新发送到Web服务器而无须用户介入。
HTTP这个特性叫做基本身份验证。使用PHP或者内置于Web服务器中的机制,可以触发这些基本身份验证。接下来,我们将讨论PHP方法、Apache方法和IIS方法。
基本身份验证以普通文本方式传输用户名和密码,因此不太安全。HTTP1.1中包含一种更安全的方法,称为摘要身份验证。摘要身份验证使用哈希算法(通常是MD5)掩饰事务处理的细节。摘要身份验证被许多Web服务器和大多数Web浏览器所最新版本所支持,但目前还有许多正在使用的浏览器早期版本不支持摘要身份验证,而且微软的IE和IIS所包含摘要验证标准的版本与非Microsoft产品并不兼容。
除了对Web浏览器的支持较差之外,摘要身份验证也不很安全。基本身份验证和摘要身份验证都只能提供低级别的安全。
基本身份验证提供的安全级别(低)与人们常用的通过Telnet或FTP连接连接一样,都是以普通文本方式传输密码的。摘要身份验证更安全一些,在传输密码之前将对密码进行加密。
当将SSL和数字证书结合起来实现基本的身份验证时,所有的Web事务处理都可以得到全面的保护。但是对于许多情况来说,一个速度快但是相对不安全的方法却是合适的方法,例如,基本身份验证。
基本身份验证只能保护特定的领域,并且要求用户提供有效用户名和密码。
指定领域是因为同一服务器上可以有多个这样的领域。同一台服务器上的不同文件和目录可以成为不同领域的一部分,每个领域由一组不同的用户名和密码来保护。指定领域也允许将一台主机或一台虚拟主机上的多个目录指定为一个领域,并用一个密码来保护它们。
 
16.4 在PHP中使用基本身份验证
一般地说,PHP脚本是跨平台的,但是基本身份验证的使用却依赖于服务器设置的环境变量。要在使用PHP作为Apache模块的Apache服务器或使用PHP作为ISAPI模块的IIS上运行一个HTTP身份验证脚本,需要检查服务器的类型并相应采取稍微不同的操作。
(代码略)
在这个例子中,用户将看到与前一个程序清单所不同的界面。我们不再提供要求输入注册信息的HTML表单。用户的浏览器将显示一个对话框。一些人认为这是一个改进,也有些人更喜欢对界面可视部分的完全控制。
因为该身份验证是通过内置于浏览器中的特性来实现的,因此浏览器将判断如何处理失败的身份验证。
Internet Explorer在显示拒绝页面之前允许用户尝试验证3次。而Netscape Navigator则允许用户尝试无数次。
 
16.5 在Apache的.htaccess文件中使用基本身份验证
Apache Web服务器包含一些油的身份验证模式,这些模式可以用于判断用户输入数据的有效性。最简单的是使用mod_auth,它将用户名-密码对与服务器中一个文本文件中的行进行比较。
要获得与前面脚本相同的输出结果,必须创建两个不同的HTML文件,一个用来显示成功登录后的内容,另一个用来显示拒绝页面。出错的时候是否显示一个网页是可选的,但是如果在显示的网页中放一些有用的东西,未尝不是一个很好的专业化做法。对于一个用户试图进入保护区域但是被拒绝而显示的网页,有用的内容可能包括如何注册一个密码,或在遗忘密码的情况下,如何通过电子邮件重设密码的说明。
(代码略)
在这个例子中,惟一有趣的地方是调用.htaccess,它将控制对目录中任何文件和子目录的访问。
可以在.htaccess文件中修改许多设置,但在我们的例子中,所做的6行修改都与身份验证有关。
第一行:ErrorDocument 401 /chapter16/rejection.html
将告诉Apache对验证失败的访问者显示什么样的文档(HTTP错误号401)。可以使用其他的ErrorDocument指令来提供不同的HTTP错误(例如,404)所需的页面,其语法如下:ErrorDocument error_number URL
对于一个处理错误401的页面,给定的URL可以被公共访问是非常重要的。如果页面锁定在一个目录里,在该目录中访问者需要成功通过验证才能浏览页面,那么提供一个自定义的错误页面告诉人们身份验证失败并不是非常有意义的。
AuthUserFile /home/book/.htpass
这一行将告诉Apache在什么地方可以找到包含已经通过身份验证的用户的密码文件。通常,这个文件是.htpass,但是我们可以给它取任何自己更喜欢的名字。文件的名称不重要,重要的是保存该文件的位置。该文件不应保存在Web树目录中——因为保存在Web树目录中的话,人们可以通过Web服务器下载它。
与指定通过身份验证的单个用户一样,指定只有在特定组中通过身份验证的用户才能访问资源也是可能的。我们选择不这样做,因此这行:AuthGroupFile /dev/null
可以将AuthGroupFile设置为指向/dev/null,这是UNIX系统中一个特殊的文件,可以保证该文件为空。
与PHP示例一样,要使用HTTP身份验证,需要命名保护区域,如下所示:AuthName "Realm_Name"
可以根据自己的喜好选择任意的区域名称,但是必须记住该名称向访问者显示。为了明显起见,我们将示例中的名称改为"Realm-Name"。
因为Apache支持许多不同的身份验证方法,必须指定使用哪一种身份验证方法。这里,我们使用的Basic身份验证方法是通过如下指令指定的:AuthType Basic
需要指定允许访问的访问者。我们可以指定特定用户、特定组,或者就像这个例子一样,只简单地允许通过身份验证的用户进行访问。代码如下:require valid-user
指定了任何有效用户都可以访问。
.htpass文件中的每一行都包含一个用户名、冒号和该用户的加密密码。
你的.htpass文件的确切内容会有所不同。要创建它,可以使用一个名为htpasswd的小程序,该程序包含在Apache软件包中。
htpasswd程序用于下列两种方法之一:htpasswd [-cmdps] passwordfile username 或者 htpasswd -b[cmdps] passwordfile username password
惟一使用的开关是-c。使用-c可以告诉htpasswd创建文件。必须在第一个添加的用户中使用这个开关。将它用于其他用户的时候要小心,因为如果该文件存在,htpasswd将删除这个文件并创建一个新文件。
该程序的可选项m、d、p或s开关可以用来指定使用哪种加密算法(包括不加密)。
开关b告诉程序要期望密码作为它的参数,而不提示输入密码。
如果要作为批处理的一部分交互地调用htpasswd,这个开关就是有意义的,但是如果从命令行调用htpasswd,就不应该使用它。
请注意,htpasswd可能没有包含在路径中:如果没有,可能需要提供其完整路径。在许多系统中,可以在/usr/local/apache/bin目录下找到它。
这种类型的身份验证容易建立,但是按照这样的方法使用.htaccess文件还存在一些问题。
用户和密码保存在同一个文本文件中。在浏览器每次请求一个被.htaccess文件保护的文件时,服务器都必须解析.htaccess文件,然后再解析密码文件,以试图匹配用户名和密码。不使用.htaccess文件,我们可以在httpd.conf文件中指定同样的事情——httpd.conf文件是该Web服务器的主配置文件。在每次请求一个文件的时候,系统都要解析.htaccess文件。而httpd.conf文件只在服务器启动有时候解析。这样速度将更快,但是也意味着,如果要做修改,需要停止并重新启动服务器。
无论将服务器指令保存在什么地方,对于每次请求,都要搜索密码文件。这就意味着,它与其他使用普通文件的技术一样,对于成千上万的用户来说,这种方法也是不合适的。
 
16.6 在IIS上使用基本身份验证
与Apache一样,IIS也支持HTTP身份验证。
(具体步骤略)
IIS方法的主要缺点在于,它是通过比较用户的注册细节与机器上的信息来完成身份验证的。如果允许一个用户用"john"用户名和密码"password"进行登录,那么我们就必须在机器上或者一个域上创建一个该用户名和密码的帐号。为Web身份验证创建帐户时要非常小心,这样才能使具有浏览Web页面帐户权限的用户无法拥有其他权限,例如Telnet访问权。
 
16.7 使用mod_auth_mysql身份验证
使用mod_auth_mysql,将拥有使用mod_auth的易用性,同时又获得访问数据库的更快速度。该模块的工作方式与mod_auth非常类似,但是因为它使用MySQL数据库而不是文本文件,所以可以在大量用户中进行搜索。
 
16.7.1 安装mod_auth_mysql
1) 获得模块的存档文件。
2) 解压缩源代码。
3) 切换到mod_auth_mysql目录,分别运行make和make install命令。必须在make文件(MakeFile)中告诉它MySQL的安装位置。
4) 在httpd.conf文件中添加如下所示行,以便动态地将模块加载到Apache:LoadModule Mysql_auth_module libexec/mod_auth_mysql.so
5) 创建数据库和包含身份验证信息的MySQL表。它并不需要是一个单独的数据库或表;可使用一个已有表。
6) 在httpd.conf文件添加mod_auth_mysql用来连接MySQL所需的参数,如下所示:Auth_MySQL_Info hostname user password
 
16.7.2 检查是否正常工作
检查编译是否正常工作的最简单方法是查看Apache是否可以启动。要启动具有SSL支持类型的Apache,可以使用如下命令:/usr/local/apache/bin/apachectl startssl
如果没有启用SSL支持类型,可以输入如下命令:/usr/local/apache/bin/apachectl start
如果启动后在httpd.conf文件中有Auth_MySQL_Info指令,mod_auth_mysql模块就已经成功添加。
 
16.7.3 使用mod_auth_mysql
在成功地安装该模块之后,使用它与使用mod_auth一样简单。
从用户观点来看,mod_auth_mysql示例的工作方式与mod_auth示例安全一样。当用户访问该网站时,都看到一个由用户浏览器给出的对话框。如果用户成功通过身份验证,浏览器将显示网页内容。如果验证失败,浏览器将显示一个出错页面。
对于许多网站来说,mod_auth_mysql是理想的。它速度快,使用相对简单,而且允许使用任何方便的机制添加新用户数据库条目。如果要求更大的灵活性以及更精确地控制网页各个部分,可能要使用PHP和MySQL来实现身份验证。
 
16.8 创建自定义身份验证
 
16.9 进一步学习
 
16.10 下一章

TAG: 学习笔记 PHP和MySQL Web开发

浪漫人生 引用 删除 lx5033   /   2007-09-28 19:09:50
5
学习蛮认真的,以后跟你学php啊~~~
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

数据统计

  • 访问量: 73099
  • 日志数: 265
  • 书签数: 19
  • 建立时间: 2007-05-03
  • 更新时间: 2008-04-15

RSS订阅

Open Toolbar