PHPRPC 與其它 ajax 框架不同,PHPRPC 遵循的是“只做一件事,并把它做好”的原則。它只負(fù)責(zé)數(shù)據(jù)傳輸,并且將傳輸做到最好!它將你以前用傳統(tǒng)的 ajax 方式做不到或者很難做到的事情變得輕而易舉!
相信好多人選擇 PHPRPC 的一個(gè)主要原因就是它能夠讓你開發(fā) ajax 應(yīng)用變得更加容易!盡管 PHPRPC 的強(qiáng)大之處不僅限于此,但我不得不承認(rèn),這確實(shí)是 PHPRPC 的一大亮點(diǎn)!
所以,我們的第一站,就來(lái)看看如何用 PHPRPC 3.0 來(lái)編寫 ajax 應(yīng)用吧。
下 面我們舉一個(gè)最簡(jiǎn)單的例子(甚至可以算是無(wú)聊的例子 :mrgreen: )來(lái)說(shuō)明如何使用 PHPRPC 3.0 編寫 ajax 應(yīng)用。這個(gè)例子很好的說(shuō)明了上面所提到的 MVC 模式如何具體的工作。這里我們先以 PHP 為服務(wù)器端的情況為例來(lái)說(shuō)明。我們的第一個(gè)例子很簡(jiǎn)單,客戶端輸入一段字符串,然后服務(wù)器端計(jì)算出它的 SHA1 值。
復(fù)制代碼代碼如下:
<?php
require_once("../php/phprpc_server.php");
$server = new PHPRPC_Server();
$server->add("sha1");
$server->start();
?>
只有這么簡(jiǎn)單的 4 行代碼,就把 PHP 內(nèi)置的 sha1 函數(shù)發(fā)布了。現(xiàn)在,客戶端可以直接使用這個(gè)函數(shù)了。
復(fù)制代碼代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>計(jì)算 SHA1</title>
<script type="text/javascript" src="../js/compressed/phprpc_client.js"></script>
<script type="text/javascript">
var rpc = new PHPRPC_Client('sha1.php', ['sha1']);
function $(id) {
return document.getElementById(id);
}
function showResult(result) {
$('sha1').value = result;
}
function sha1() {
var input = $('sha1').value;
$('sha1').value = "Loading...";
rpc.sha1(input, showResult);
}
</script>
</head>
<body>
<input type="text" id="sha1" />
<input type="button" value="計(jì)算 SHA1" onclick="sha1()" />
</body>
</html>
這個(gè)例子非常簡(jiǎn)單,并且跟 PHPRPC 有關(guān)的只有兩條語(yǔ)句,一條是:
復(fù)制代碼代碼如下:
var rpc = new PHPRPC_Client('sha1.php', ['sha1']);
這條語(yǔ)句用來(lái)創(chuàng)建一個(gè) PHPRPC_Client 對(duì)象,第一個(gè)參數(shù)是服務(wù)器地址,這里可以用相對(duì)路徑,也可以用絕對(duì)路徑。
而且這個(gè)路徑可以跨域!因此你可以做跨域的應(yīng)用!
第二個(gè)參數(shù)是你需要使用的服務(wù)器端的函數(shù)名列表,所以,雖然我們這里只有一個(gè)函數(shù),也要寫成數(shù)組的形式。這樣我們就有了一個(gè)可以調(diào)用服務(wù)器端方法的客戶端對(duì)象了。
那該如何調(diào)用呢?我們來(lái)看第二條關(guān)于 PHPRPC 的語(yǔ)句:
復(fù)制代碼代碼如下:
rpc.sha1(input, showResult);
這條語(yǔ)句相當(dāng)簡(jiǎn)單,你會(huì)發(fā)現(xiàn)我們直接使用了服務(wù)器端發(fā)布的函數(shù)名作為 rpc 對(duì)象的一個(gè)方法來(lái)調(diào)用。它的第一個(gè)參數(shù)就是 sha1 函數(shù)的參數(shù)值。第二個(gè)參數(shù)是個(gè)函數(shù),這個(gè)是回調(diào)函數(shù),也就是說(shuō),當(dāng)服務(wù)器端方法執(zhí)行完之后就會(huì)自動(dòng)調(diào)用這個(gè)函數(shù)來(lái)完成結(jié)果的處理。它是在前面定義的,你會(huì) 發(fā)現(xiàn)它有一個(gè)參數(shù) result,這個(gè)參數(shù)就是我們的遠(yuǎn)程過(guò)程 sha1 的返回值,它是通過(guò)回調(diào)函數(shù)的這個(gè)參數(shù)傳入的。
另外一篇文章,整理的代碼比較詳細(xì)
昨天我舉了個(gè)用 PHPRPC 實(shí)現(xiàn) Ajax 級(jí)聯(lián)下拉菜單 的例子,那個(gè)例子中我們重點(diǎn)要演示的是用 PHPRPC 實(shí)現(xiàn) Ajax 效果是多么的簡(jiǎn)單。今天我們這個(gè)例子主要演示用 PHPRPC 內(nèi)置的安全加密機(jī)制來(lái)實(shí)現(xiàn)安全登錄是多么簡(jiǎn)單。當(dāng)然它同樣可以用于密碼設(shè)置、其它關(guān)鍵保密數(shù)據(jù)的傳輸?shù)阮I(lǐng)域。
這個(gè)例子比昨天的例子還要簡(jiǎn)單,先來(lái)看服務(wù)器端:
復(fù)制代碼代碼如下:
<?php
function login($username, $password) {
if (($username == "root") && ($password == "admin")) {
$_SESSION['user'] = "root";
return true;
}
$_SESSION['user'] = null;
return false;
}
require_once("phprpc_server.php");
new phprpc_server(array('login'));
?>
這段代碼太簡(jiǎn)單了,我不需要多說(shuō)什么大家也能夠看明白。不過(guò)大家會(huì)發(fā)現(xiàn),在 login 函數(shù)中我用了 $_SESSION 變量,但是并沒(méi)有在什么位置上寫 session_start(),原因在于建立加密連接時(shí),已經(jīng)自動(dòng)調(diào)用了 session_start(),因此不需要再單獨(dú)寫 session_start() 了。為了驗(yàn)證它是否生效,我們?cè)诤竺娴牧硪粋€(gè)頁(yè)面中(admin.php),將判斷這里設(shè)置的 $_SESSION 變量,并根據(jù)它來(lái)報(bào)告登錄成功或者沒(méi)成功跳回到登錄頁(yè)面。
那再來(lái)看看客戶端,客戶端我們將 JavaScript 跟 HTML 分離了,先來(lái)看看 html 頁(yè)面。
復(fù)制代碼代碼如下:
<html>
<head>
<script type="text/javascript" src="phprpc_client.js"></script>
<script type="text/javascript" src="login.js"></script>
</head>
<body>
<div align="center">
帳號(hào):<input type="text" id="username" />
密碼:<input type="password" id="password" />
<input type="button" value="登錄" id="loginbtn" />
</div>
</body>
</html>
這個(gè)頁(yè)面很簡(jiǎn)單,只是設(shè)置好了表單輸入框和按鈕,所有的處理都是在 login.js 中完成的。不過(guò)需要注意的是這里的 phprpc_client.js 是 full 壓縮版本,因?yàn)槲覀冃枰玫剿募用軅鬏敼δ堋N覀儊?lái)看看 login.js 是怎么寫的。
復(fù)制代碼代碼如下:
// 創(chuàng)建 phprpc 客戶端對(duì)象 rpc
phprpc_client.create('rpc');
// 初始化帶有加密連接的 rpc 服務(wù),第二個(gè)參數(shù)表示是否創(chuàng)建加密連接
rpc.use_service('rpc.php', true);
// 登錄函數(shù)
function login() {
// 如果加密連接已經(jīng)初始化完畢,則驗(yàn)證用戶名密碼
if (rpc.ready) {
// 獲取用戶輸入的用戶名和密碼
var username = document.getElementById('username').value;
var password = document.getElementById('password').value;
// 設(shè)置遠(yuǎn)程過(guò)程調(diào)用為單向加密,
// 即傳遞的參數(shù)是加密的,但返回結(jié)果不加密
rpc.encrypt = 1;
// 調(diào)用遠(yuǎn)程過(guò)程驗(yàn)證用戶名密碼是否正確,并設(shè)置回調(diào)函數(shù)。
rpc.login(username, password, function (result) {
// 如果返回結(jié)果正確,則轉(zhuǎn)到登錄后的頁(yè)面
if (result === true) {
window.location.replace('admin.php');
}
// 否則提示用戶名密碼不正確
else {
alert('用戶名密碼不正確!');
}
});
}
// 如果連接尚未初始化完畢,則等待 100 毫秒后重試。
else {
window.setTimeout('login();', 100);
}
}
window.onload = function () {
document.getElementById('loginbtn').onclick = login;
}
大家會(huì)發(fā)現(xiàn)除了在調(diào)用 use_service 時(shí),設(shè)置了第二個(gè)參數(shù)為 true 外,還在調(diào)用服務(wù)器端的 login 函數(shù)前,設(shè)置了 rpc.encrypt 的值為 1,這里 1 表示單向加密傳輸,單向加密傳輸是指調(diào)用的參數(shù)會(huì)以加密的方式傳給服務(wù)器,但是返回的結(jié)果不加密(如果參數(shù)是引用參數(shù)的話,參數(shù)返回時(shí)也是加密的)。如果 rpc.encrypt 的值為 0,則表示不加密;如果是 2,則表示雙向加密。
這里因?yàn)橹挥杏脩裘兔艽a是敏感數(shù)據(jù),需要保證它在傳遞給服務(wù)器時(shí)不被截獲(即使截獲也是加密的內(nèi)容,無(wú)法破解),但返回的結(jié)果成功還是不成功并不是什么需要保密的數(shù)據(jù),所以可以不加密。因此這里選擇了單向加密傳輸。
大家也不必?fù)?dān)心密鑰是否會(huì)被截獲,因?yàn)槊荑€是通過(guò)密鑰交換算法,在服務(wù)器端和客戶端(瀏覽器端)隨機(jī)同步生成的,但沒(méi)有經(jīng)過(guò)網(wǎng)絡(luò)傳輸,在網(wǎng)絡(luò)上傳輸?shù)氖巧赏矫荑€的相關(guān)信息,但是只獲取到這些信息是不足以算出密鑰的,因此可以保證密鑰的安全性。而加密算法本身也是一個(gè)強(qiáng)加密算法,密鑰長(zhǎng)度是 128 位,在沒(méi)有密鑰的情況下采用窮舉法也是無(wú)法破解的。
大家會(huì)發(fā)現(xiàn)登錄成功后,我們轉(zhuǎn)向了 admin.php 頁(yè)面,下面是這個(gè)頁(yè)面的一個(gè)簡(jiǎn)單的例子:
復(fù)制代碼代碼如下:
<?php
session_start();
if ($_SESSION['user'] == 'root') {
echo "登錄成功!";
}
else {
header("Location: index.html");
}
?>
這里需要自己 sestion_start() 一下了,之后就可以驗(yàn)證 $_SESSION['user'] 是否設(shè)置了。
通過(guò) PHPRPC,你不再需要為 Ajax 程序中數(shù)據(jù)的安全性而頭痛,也不必為回話支持而苦惱,這一切 PHPRPC 都已經(jīng)幫你自動(dòng)完成了,你只需要關(guān)注具體的事務(wù)就可以了。用 PHPRPC 來(lái)做 Ajax 安全編程,就是這么簡(jiǎn)單!