程序的思路主要是:頁面加載時調用init判斷客戶端是否存有網站所需的cookies,如果有的話取相應cookies到服務端驗證,通過驗證顯示成功提示,反之顯示登錄框,同樣如果沒有所需cookIEs也顯示登錄框直到用戶輸入正確的用戶名和密碼。整個過程兩次用到了AJax,一次是用戶輸入用戶名和密碼點擊登錄按鈕後,另一次是頁面加載時的用戶名和密碼驗證,其實兩個過程調用的是同一個函數parseLogin,這個函數主要負責與遠程(也就是“?action=login”)通訊,而“?action=login”接受post過來的用戶名和密碼進行處理並返回處理結果,客戶端收到服務端的處理結果後進行進一步的處理(調用函數makeResult)。可以看出與傳統的“處理登錄”相比是有很大差別的,首先整個過程中沒有任何的頁面加載(也就是無刷新),form中我並沒有指定action和method,由JS完成與PHP的通信,同時也是異步的(你可以同時進行多個請求,而按傳統方式在進行一個請求時不能再進行其他請求(使用多個iframe也可以模擬出異步的效果,這裡不包括這種情況)),充分利用這兩點就可以制作出以前需要通過非常復雜的方法才可能達到的效果,如自動完成等。
客戶端使用的prototype.JS,實際上從我第一眼發現這個強悍無比的家伙時就離不了它了,還狠心“拋棄”了已經很習慣的SAJax。另外服務端返回的是XML,在這裡使用XML只是想說明一種通用的JS處理XML的方式。
當然由於是無刷新的,所以在提交登錄時已經看不到狀態欄上的進度條,如果登錄時間過長,用戶可能不知道發生了什麼事情,會不停的點擊提交,這時我們一般會在提交時生成一個加載條,告訴用戶目前正在發生什麼,如gmail右上角的loading...,chinaren的“我正在幫您登錄,請稍等...”,當服務端返回結果時就要隱藏這個加載條,控制display屬性就可以簡單的實現這種輪換效果
<?PHP
/**************************************************************
* login.PHP
* @author Java中文網
* @email hi@Javaweb.cc
* @note AJax登錄驗證,用戶名和密碼保存在客戶端cookIEs中
**************************************************************/
//得到安全字符串
function safe_str($str)
{
return (string)Htmlspecialchars(trim($str));
}
if(safe_str($_GET['action'])=='login')
{
//登錄驗證
header("Content-type: text/XML");
$user=safe_str($_POST['user']);
$pwd=safe_str($_POST['pwd']);
$response_XML='<info>';
//只有當用戶名為root,密碼為888時才通過驗證
$response_XML.=($user!='root'||$pwd!='888')?'<error>incorrect username or passWord!</error>':"<login><info><user>{$user}</user><pwd>{$pwd}</pwd></info></login>";
$response_XML.='</info>';
print $response_XML;
exit;
}
else
{
?>
<Html>
<head>
<title>AJax登錄驗證</title>
<script type="text/Javascript" src="prototype.JS"></script>
<script language="Javascript" type="text/Javascript">
<!--
//得到cookIEs的值
function getCookIE(name)
{
var dc=document.cookIE;
var prefix=name+"=";
var begin=dc.indexOf("; "+prefix);
if(begin==-1)
{
begin=dc.indexOf(prefix);
if(begin!=0)
return "";
}
else
begin+=2;
var end=document.cookIE.indexOf(";",begin);
if(end==-1)
end=dc.length;
return unescape(dc.substring(begin+prefix.length,end));
}
//刪除cookIEs
function delCookIE(name)
{
if(getCookIE(name))
document.cookIE=name+"=; path=/; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
//設置cookIEs
function setCookIE(name,value)
{
var expires=new Date();
expires.setTime(expires.getTime()+30*24*60*60*1000); //設置cookIEs失效時間為一個月
document.cookIE=name+"="+escape(value)+"; expires="+expires.toGMTString()+"; path=/";
}
//得到節點的值
function getElementTextNS(local,parentElem,index)
{
var result = parentElem.getElementsByTagName(local)[index];
return result?result.childNodes.length>1?result.childNodes[1].nodeValue:(result.firstChild?result.firstChild.nodeValue:""):"n/a";
}
//初始化
function init()
{
var loginUser=getCookIE("AJaxUser");
var loginPwd=getCookIE("AJaxPwd");
loginUser!=""?parseLogin(loginUser,loginPwd):genLoginForm();
}
//退出登錄
function logOut()
{
delCookIE("AJaxUser");
delCookIE("AJaxPwd");
genLoginForm();
}
//用指定的用戶名和密碼登錄
function parseLogin(username,passWord)
{
var postBody="user="+escape(username)+"&pwd="+escape(passWord);
new AJax.Request("?action=login", {method:"post", postBody:postBody,
onFailure:function() {alert("程序異常")},
onSuccess:makeResult});
return false;
}
//處理登錄返回結果
function makeResult(response)
{
var info=response.responseXML.getElementsByTagName("info");
var error=getElementTextNS("error",info[0],0);
if(error!="n/a")
{
genLoginForm();
alert("請輸入正確的用戶名和密碼");
}
else
{
var user=getElementTextNS("user",info[0],0);
var pwd=getElementTextNS("pwd",info[0],0);
setCookIE("AJaxUser",user);
setCookIE("AJaxPwd",pwd);
if(getCookIE("AJaxUser")=="")
{
genLoginForm();
alert("您的浏覽器必須支持cookIEs");
}
else
$("content").innerHtml="<h2>Hello,<font color=\"red\">"+user+"</font>!<a href=\"Javascript:logOut();\">logout</a></h2>";
}
}
//顯示登錄框
function genLoginForm()
{
$("content").innerHtml="<form onsubmit=\"return parseLogin($('user').value,$('pwd').value);\">用戶名:<input type=\"text\" id=\"user\" size=\"12\"> 密碼:<input type=\"passWord\" id=\"pwd\" size=\"12\"> <input type=\"submit\" value=\"登錄\"></form>";
}
//-->
</script>
</head>
<body onload="init();">
<div id="content"></div>
</body>
</Html>
<?PHP
}
?>