由于在用户进行注册前,不能完成除浏览之外的任何操作,因此我们首先来讲解用户模块的制作。用户模块一般分为注册、登录、信息修改三个功能,另外,还可以有密码找回功能,本节将对这些功能依次进行讲解。
在本案例中,打开页面regist.asp或者在网站页面的侧边栏点击“注册”并填写注册表单提交,都将打开页面regist.asp,实际上,侧边栏部分是将regist.asp页面中的表单提取出来放置的,因此我们主要来看regist.asp页面。
此页面通过GET方式请求,显示表单的部分,我们省去不谈,如果需要,你可以查看本书附送光盘中chapter7下的文件(由于篇幅原因,从本章开始,显示表单的HTML代码如无特殊,均省略)。当提交表单至本页面后,将进入如下处理:
'如果以POST方式发送数据到本页,则
If PostBack() Then
'……省略变量定义
'获取用户输入内容
sEmail = Trim(Request.Form("reg_email"))
sPassword = Trim(Request.Form("reg_password"))
'使用正则验证用户输入合法性
If doReTest(sEmail,"\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$") = False Then
'注意这里我给出了另一种验证Email的正则表达式
ShowError "您输入的Email格式可能有误!"
End If
If doReTest(sEmail,".{6,15}") = False Then
ShowError "您输入的密码应该是6-15位!"
End If
'将用户密码使用MD5进行加密
sPassword = MD5(sPassword)
'判断该用户邮箱是否已经被注册
Set oRs = Server.CreateObject("ADODB.RecordSet")
'在数据库中选取邮箱为用户填写邮箱的用户
sql = "SELECT * FROM [ShareUser] WHERE UserEmail='" & sEmail & "'"
oRs.Open sql,oConn,1,3
'如果存在,说明已经被注册,则提示错误
If oRs.RecordCount >0 Then
oRs.Close
Set oRs = Nothing
oConn.Close
Set oConn = Nothing
ShowError "您输入的Email已经注册过了,如果忘记密码,您可以找回密码!"
'否则进入注册
Else
oRs.AddNew() '添加新记录
'设定新纪录各字段的值
oRs("UserEmail") = sEmail
oRs("UserPassword") = sPassword
oRs("UserAddTime") = Now()
'更新记录集
oRs.Update
'获得新注册的用户编号
oRs.MoveLast
lID = oRs("UserID")
oRs.Close
Set oRs = Nothing
'为用户增加其默认的相册
sql = "INSERT INTO [Album] (UserID,AlbumName) VALUES (" & lID & ",'默认相册')"
'执行增加默认相册的SQL语句
oConn.Execute sql
Set oConn = Nothing
'调用LoginSession过程并传入相应参数来处理登录
LoginSession lID,sEmail,sPassword
ShowSuccess "注册成功!"
End If
Response.End()
End If
在这段程序中,进行了如图8.9的处理:
图8.9
程序首先通过Request.Form集合获得用户填写的表单信息,而后使用自定义的正则表达式函数doReTest对其进行了正则测试,如果符合我们预设的正则表达式,则认为其是合法的,否则提示错误。
而后程序打开记录集,从数据库的ShareUser表中选取用户输入的Email的记录,如果记录集不为空,那么说明该Email已经被注册,此时提示错误,否则就使用oRs.AddNew方法加入一条新记录,而后通过oRs.MoveLast将记录集的指针移到末端,此时记录集指针对应的就是新加入的记录,我们读出此时的oRs("UserID")的值,即新加入的用户的编号,而后生成sql语句,为用户加入其默认的相册。最后完成注册操作。
你应该注意到了在上面的源代码中,有这样一句,sPassword = MD5(sPassword),这里我使用MD5()这个自定义函数对用户输入的密码sPassword进行了处理,即,我使用MD5算法对用户密码进行了加密之后才放入数据库。
MD5的全称是Message-Digest Algorithm 5(信息-摘要算法第五版),它的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。MD5算法是一种不可逆算法,即,我们使用MD5对密码原文进行加密,得到一个密码密文(无论原文如何,密文的长度总是固定的,一般来说,有32位和16位两种,其中16位是取32位密文的中间16位),而通过密文,无论我们如何运算,原则上都不能够得到密码的原文。
MD5的不可逆特性为我们的加密提供了方便,我们将用户的密码加密后存放在数据库当中,这样做的目的有二,第一,免除了网站管理员通过查看数据库,而得知用户密码的“嫌疑”,因为毕竟密码也算作一种隐私(很多人在所有网站注册用户,密码总是用相同的,这样一旦一个密码泄露,得知密码的人就可以登录其注册的所有网站了)。第二,即使黑客通过种种手段下载了网站的数据库,得知了数据库中保存的密码密文,由于不能够通过密文得到原文,他也无法从登录到网站上。
在实际的使用中,我们将用户输入的密码进行MD5加密,保存在数据库中,当用户登录时,我们再次将用户登录所输入的密码进行MD5加密,并与数据库中经过加密的字符串进行比对。以实现对用户密码的有效保存。
这里MD5加密的相关函数定义在include/lib/md5.asp中,如果有兴趣,你可以打开此文件,来学习其加密算法,如果没有兴趣,那么你可以在需要加密的时候,使用MD5()函数即可。
用户登录是通过login.asp页面来完成的,这个页面获取用户输入的Email和密码,并在数据库中进行判断,该部分代码如下:
<%
If PostBack() Then
Dim rs
Dim sql
Dim sEmail
Dim sPassword
'获取用户输入内容并进行合法性检验
sEmail = Trim(Request.Form("login_email"))
sPassword = Trim(Request.Form("login_password"))
If doReTest(sEmail,"\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$") = False Then
ShowError "您输入的Email格式可能有误!"
End If
If doReTest(sEmail,".{6,15}") = False Then
ShowError "您输入的密码应该是6-15位!"
End If
'将密码使用MD5函数加密
sPassword = MD5(sPassword)
'建立记录集对象的实例rs
Set rs = Server.CreateObject("ADODB.RecordSet")
'取出相应用户名(邮箱)的记录
sql = "SELECT * FROM [ShareUser] WHERE UserEmail='" & sEmail & "'"
rs.Open sql,oConn,1,3
'如果有记录,则说明用户存在
If rs.RecordCount >0 Then
'继续验证密码
If rs("UserPassword") = sPassword Then
'如果密码的MD5密文和数据库中保存的密文相等,则处理登录
LoginSession rs("UserID"),sEmail,sPassword '调用LoginSession过程
'关闭并清空记录集和数据库链接,以回收资源
rs.Close
Set rs = Nothing
oConn.Close
Set oConn = Nothing
'提示成功信息
ShowSuccess "登录成功!"
Else
'关闭并清空记录集和数据库链接,以回收资源
rs.Close
Set rs = Nothing
oConn.Close
Set oConn = Nothing
'提示失败信息
ShowError "您输入的密码错误!"
End If
'否则说明用户不存在
Else
'关闭并清空记录集和数据库链接,以回收资源
rs.Close
Set rs = Nothing
Set oConn = Nothing
'提示成功信息
ShowError "您输入的Email不存在!"
End If
Response.End()
End If
%>
用户登录过程我们已经多次涉及过了,这里的登录过程与前面的并无不同,因此我仅简单说一下。
程序首先从Request.Form集合中获取用户所填写的用户名和密码,而后和用户注册部分一样的,也适用正则测试的方法对用户输入的合法性进行了判断。而后程序打开记录集,从数据库的ShareUser表中选取相应Email的记录,而后进行判断,如果记录集为空,那么提示输入的Email不存在,否则再对用户输入的密码数据和数据库中的数据进行比对,如果相同,则调用自定义过程LoginSession将用户的登录信息保存在session中,否则提示错误。
用户密码找回是用户模块中一个必要的部分,因为用户往往会由于自己忘记密码,或者帐户被盗,而导致需要找回密码。
通常来讲,用户密码找回有这样两种形式,第一种是用户在注册时填写一个密码提示问题和提示问题的答案,当用户忘记密码时,其可以在找回密码处输入用户名,网站给出其提示问题,要求填写提示问题的答案。而第二种则是网站根据用户在注册时填写的Email,向其电子邮箱中发送一封信件,在这个信件中指定了一个URL,这个URL中通过QueryString向网站传送一串随机字符串,作为密钥,用户打开此URL后即可更改密码。另外还有两种方式结合的方法,以提高安全性。在本案例中,主要采取第二种发送Email的方法。
这里的密钥原理是这样的,当用户在找回密码处输入用户名,而后程序生成一段随机字符串保存在数据库中,而后将此随机字符串发送到用户注册时填写的Email中,而后当用户打开邮件中的Url后,网站程序将其传递来的密钥与数据库中的进行比对,如果符合,就显示修改密码的表单。
所以,你可以很容易的发现到,这个功能需要两个页面来完成,本案例中,他们分别是getpassword.asp和findpass.asp。
首先我们来看生成密钥并发送的页面getpassword.asp,此页面当以GET方式请求时显示让用户填写其注册时邮箱的表单,当以POST方式请求时,进行如下处理:
<%
If PostBack() Then
Dim oRs,sql,i
Dim lUserID
Dim sUserEmail
Dim sPrivateKey
'获取用户输入信息
sUserEmail = Trim(Request.Form("UserEmail"))
'取出用户记录
Set oRs = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM [ShareUser] WHERE UserEmail = '" & sUserEmail & "'"
'打开记录集
oRs.Open sql,oConn,1,1
'如果用户不存在
If oRs.EOF AND oRs.BOF Then '如果记录集为空
'关闭和清空记录集和数据库链接
oRs.Close
Set oRs = Nothing
oConn.Close
Set oConn = Nothing
'提示错误信息
ShowError "您输入的Email还没有被注册呢!"
'否则如果用户存在
Else
'获得用户编号以待后续使用
lUserID = oRs("UserID")
'及时关闭记录集和清空记录集变量
oRs.Close
Set oRs = Nothing
'通过GenRadomString函数生成密钥
sPrivateKey = GenRadomString(30)
'向表FindPass加入一条修改密码请求
sql = "INSERT INTO [FindPass] (UserID,PrivateKey,FindAddTime) VALUES (" & lUserID & ",'" & sPrivateKey & "',#" & Now() & "#)"
'调用oConn对象的Execute方法执行SQL命令
oConn.Execute sql
'关闭和清空数据库链接
oConn.Close
Set oConn = Nothing
'调用自定义函数SendMail向用户发送Email
SendMail sUserEmail,"您在WeShare的密码找回信息","您好,请点击以下链接回到WeShare重置您的密码(请注意,密码尽在24小时内有效!):http://www.weshare.cn/findpass.asp?PK=" & sPrivateKey & ""
'提示成功信息
ShowSuccess "您的密码找回链接已经发送到您的Email:" & sUserEmail & "中..."
End If
End If
%>
程序首先获得用户填写的表单中其邮箱地址,而后打开记录集,查询ShareUser表中相应的记录,如果记录集为空,则提示该Email还没有注册,否则先利用GenRadomString函数生成一个长度为30的随即字符串,而后生成INSERT指令的SQL命令并执行,以向密钥表FindPass中插入一条找回密码的记录。而后程序调用过程SendMail向用户的邮箱中发送信件。(注意在调试本页面的时候,请确保您在自己的计算机上已经安装了Jmail组件,如果没有安装,请参考第三章相应内容)
此时用户打开邮箱,会收到如图8.10的邮件:
图8.10
当用户打开此链接后,进入findpass.asp页面的处理,此页面源代码如下:
<%
Dim oRs,sql,i
Dim lUserID
Dim sUserEmail
Dim sPrivateKey
'获取用户修改密码密钥
sPrivateKey = Replace(Trim(Request("PK")),"'","''")
'根据密钥取出密码修改请求
Set oRs = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM [FindPass] WHERE PrivateKey = '" & sPrivateKey & "' AND DateDiff('h',Now(),FindAddTime)<=24"
'打开记录集
oRs.Open sql,oConn,1,1
'如果请求不存在
If oRs.EOF AND oRs.BOF Then '如果记录集为空,说明密码找回链接无效
'关闭和清空记录集以及数据连接
oRs.Close
Set oRs = Nothing
oConn.Close
Set oConn = Nothing
'提示错误
ShowError "您的找回密码链接无效。"
Else
lUserID = oRs("UserID")
oRs.Close
End If
'如果是以POST方式请求页面,则说明此时进入了修改密码环节
If PostBack() Then
Dim sNewPassword
'获取用户输入的新密码
sNewPassword = Trim(Request.Form("password"))
'打开记录集,取出用户信息,以便修改
sql = "SELECT * FROM [ShareUser] WHERE UserID=" & lUserID
oRs.Open sql,oConn,1,3
'如果帐户不存在
If oRs.EOF AND oRs.BOF Then '如果记录集为空
'关闭记录集并提示错误信息
oRs.Close
Set oRs = Nothing
oConn.Close
Set oConn = Nothing
ShowError "您的帐户已经不存在了!请联系管理员!"
'如果帐户存在则修改其密码
Else
oRs("UserPassword") = MD5(sNewPassword)
oRs.Update
End If
oRs.Close
Set oRs = Nothing
'删除表FindPass中的找回密码请求
sql = "DELETE FROM [FindPass] WHERE PrivateKey = '" & sPrivateKey & "'"
'执行删除的SQL命令
oConn.Execute sql
'关闭和清空数据连接
oConn.Close
Set oConn = Nothing
ShowSuccess "您的密码已经更新成功!请重新登录即可"
End If
%>
此页面将实现读取用户发送的密钥以及用户修改密码的两个操作,因此在页面的顶部,无论当前页请求方式是GET还是POST,都会进行判断其所输入的密钥是否存在的过程。这里获取用户传递来的密钥是通过Request集合,而并非Request.QueryString集合,这是因为当用户点击链接后,打开页面,如果密钥合法,则会在此页面显示一个表单,并以隐藏域保存密钥,以待发送表单至本页面时使用。
程序获取用户传递来的密钥,而后打开记录集,取出数据库中相应密钥对应的记录,如果不存在,则提示错误,如果存在,则读取出密钥对应的用户编号,保存在变量lUserID中。
而后如果当前页面是以Post方式请求,那么进入下面的修改密码的处理环节。
程序首先根据lUserID变量,打开ShareUser表中相应用户的记录,并将其UserPassword字段修改为用户提交的值,最后还需要执行SQL语句,删除FindPass表中相应的记录,以保证帐户安全。
用户资料修改部分(account.asp)可以提供给用户一个修改其头像、昵称以及密码的部分,如图8.11所示。
图8.11
这里我首先谈一个特殊的地方,就是对密码的修改,你应当还记得,我们这个案例将用户的密码以不可逆加密形式保存在数据库中,因此在修改密码界面,我们不能显示出用户密码的信息了,因此这里我们使用了一个checkbox的HTML表单域,当选中此checkbox后,将要求用户输入原密码和新密码,以对密码进行修改,否则程序自动略过修改密码的部分。
如果在修改密码的地方不注意,则很可能出现问题,可能的问题有两种:第一,你选择在页面上的密码文本框中显示数据库中的信息,由于此时数据库中保存的是密码的MD5密文,你将其显示出来,在修改时肯定又将其加密一次(因为你不知道此时用户是否修改了密码,只能按照已经修了密码来操作),这样用户保存在数据库中的密文实际上是其密码原文经过两次MD5后的,这样他下次再登录时,就会提示密码错误;第二,你选择在页面上的密码文本框中显示空字符串,基于和上面所述一样的原因,你可能会将数据库中保存的密文修改为空字符串的MD5值,也会出现用户无法登录的情况。
来看此部分的代码:
<%
'因为只有登录后才能修改密码,因此先检测是否登录
If IsLogined = False Then
ShowError "请登录!"
Response.End()
End If
'……省略变量定义过程
'获取用户输入的值
lID = Trim(Session("weshare_UserID"))
sUserNickName = Request.Form("UserNickName")
sUserHead = Request.Form("UserHead")
sOldPassword = Trim(Request.Form("OldPassword"))
sOldPassword = MD5(sOldPassword)
sNewPassword = Trim(Request.Form("NewPassword"))
sNewPassword = MD5(sNewPassword)
'打开记录集取出当前用户记录
Set oRs = Server.CreateObject("ADODB.RecordSet")
sql = "SELECT * FROM [ShareUser] WHERE UserID=" & lID
oRs.Open sql,oConn,1,3
If oRs.RecordCount =0 Then '如果用户不存在,则提示错误
oRs.Close
Set rs = Nothing
oConn.Close
Set oConn = Nothing
ShowError "没有这个用户!"
Else '如果用户存在,则分为以POST方式或者以GET方式请求的不同来操作
'如果提交表单则更新到数据库
If PostBack() Then
'设定数据库中信息为用户提交的信息
oRs("UserNickName") = sUserNickName
oRs("UserHead") = sUserHead
'更新记录集
oRs.Update
'处理修改密码的过程
If Trim(Request.Form("ChangePassword")) = "change" Then '如果选中了checkbox(选择框)
If sOldPassword = oRs("UserPassword") Then '如果旧密码输入正确
'更新密码
oRs("UserPassword") = sNewPassword
LoginSession lID,oRs("UserEmail"),sNewPassword
Else '如果旧密码输入错误
'提示旧密码错误
ShowError "您输入的旧密码错误!"
End If
End If
oRs.Update
CloseDb()
ShowSuccess "用户信息修改成功!"
'否则从数据库中取出信息保存在临时变量中以待显示
Else
sUserNickName = oRs("UserNickName")
sUserHead = oRs("UserHead")
oRs.Close
Set oRs = Nothing
End If
End If
%>
在程序的开始部分,首先对用户是否登录进行了判断:如果用户没有登录,那么其自然不能修改密码。
而后程序从session变量集合中获取当前登录的用户的编号,并打开记录集从ShareUser表中取出当前用户的记录。
在取出完毕后,对当前页面的请求方式不同,进行了不同的分支。
如果当前页面是以POST方式请求,那么就获取表单内容,并更新在数据库当中,你需要特别注意这里对密码部分的处理,仅当Trim(Request.Form("ChangePassword")) = "change"时,才进入下面更新密码的部分。
如果当前页面是以GET方式请求,则将数据库中的相应信息保存在本地变量sUserNickName和sUserHead当中,以便下面的HTML表单使用。
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛