2010年5月31日 星期一

[Zend Framework] OpenId範例

<< test_auth.php範例程式說明 >>

<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_OpenId
* @subpackage Demos
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

$dir = realpath(dirname(__FILE__)."/../../..");
set_include_path("$dir/incubator/library" . PATH_SEPARATOR . "$dir/library" . PATH_SEPARATOR . get_include_path());

/**
* @see Zend_Auth
*/
require_once "Zend/Auth.php";

/**
* @see Zend_Auth_Adapter_OpenId
*/
require_once "Zend/Auth/Adapter/OpenId.php";

$status = "";
$auth = Zend_Auth::getInstance();

//判斷使用者是否輸入OpenID進行登入處理程序
if ((isset($_POST['openid_action']) &&
$_POST['openid_action'] == "login" &&
!empty($_POST['openid_identifier'])) ||
isset($_GET['openid_mode']) ||
isset($_POST['openid_mode'])) {
//向使用者輸入OpenID所屬的OpenID Provider請求認證
$result = $auth->authenticate(
new Zend_Auth_Adapter_OpenId(@$_POST['openid_identifier']));
if ($result->isValid()) {
//OpenID認證成功
//將使用者重導到原先向OpenID Provider請求認證的PHP程式網址
Zend_OpenId::redirect(Zend_OpenId::selfURL());
} else {
//OpenID認證失敗,通常得到的錯誤訊息為「Authentication failed」
//失敗的原因可能是輸入的OpenID不存在或使用者拒絕認證
$auth->clearIdentity();
foreach ($result->getMessages() as $message) {
$status .= "$message<br>\n";
}
}
//這部份是已經向OpenID Provider請求認證後重導回來,進行後續工作的程式碼
} else if ($auth->hasIdentity()) {
if (isset($_POST['openid_action']) &&
$_POST['openid_action'] == "logout") {
//使用者登出(logout)
$auth->clearIdentity();
} else {
//使用者OpenID認證成功,顯示以下訊息:
//You are logged-in as 使用者OpenID .
$status = "You are logged-in as " . $auth->getIdentity() . "<br>\n";
}
}
//顯示要求使用者選擇「輸入OpenID進行登入」或是「登出」的Form
?>
<html><body>
<?php echo "$status";?>
<form method="post"><fieldset>
<legend>OpenID Login</legend>
<input type="text" name="openid_identifier" value="">
<input type="submit" name="openid_action" value="login">
<input type="submit" name="openid_action" value="logout">
</fieldset></form></body></html>

<< test_consumer.php範例程式說明 >>

<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_OpenId
* @subpackage Demos
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

$dir = realpath(dirname(__FILE__)."/../../..");
set_include_path("$dir/library" . PATH_SEPARATOR . get_include_path());

/**
* @see Zend_OpenId_Consumer
*/
require_once "Zend/OpenId/Consumer.php";

/**
* @see Zend_OpenId_Extension_Sreg
*/
require_once "Zend/OpenId/Extension/Sreg.php";

$id = "";
$status = "";
$data = array();
//判斷使用者是否輸入OpenID進行登入處理程序
if (isset($_POST['openid_action']) &&
$_POST['openid_action'] == "login" &&
!empty($_POST['openid_identifier'])) {

$consumer = new Zend_OpenId_Consumer();
$props = array();
//確認使用者決定有那些個人資料要由OpenID Provider提供給目前正在進行OpenID認證的網站
foreach (Zend_OpenId_Extension_Sreg::getSregProperties() as $prop) {
if (isset($_POST[$prop])) {
if ($_POST[$prop] === "required") {
$props[$prop] = true;
} else if ($_POST[$prop] === "optional") {
$props[$prop] = false;
}
}
}
$sreg = new Zend_OpenId_Extension_Sreg($props, null, 1.1);
$id = $_POST['openid_identifier'];
//判斷傳送OpenID給所屬的OpenID Provider是否失敗
//將使用者重導至OpenID Provider後,會讓使用者選擇要傳送的個人資料與認證方式
if (!$consumer->login($id, null, null, $sreg)) {
$status = "OpenID login failed";
}
//判斷傳送OpenID給所屬的OpenID Provider認證的結果
//這部份是已經向OpenID Provider請求認證程後重導回來,進行後續工作的程式碼
} else if (isset($_GET['openid_mode'])) {
//openid_mode=id_res:進一步判斷OpenID是否為有效
//openid_mode=cancel:使用者在OpenID Provider選擇拒絕認證
if ($_GET['openid_mode'] == "id_res") {
$sreg = new Zend_OpenId_Extension_Sreg();
$consumer = new Zend_OpenId_Consumer();
//VALID 使用者OpenID:OpenID有效且使用者同意認證
//INVALID 使用者OpenID:OpenID無效
if ($consumer->verify($_GET, $id, $sreg)) {
$status = "VALID $id";
$data = $sreg->getProperties();
} else {
$status = "INVALID $id";
}
} else if ($_GET['openid_mode'] == "cancel") {
$status = "CANCELED";
}
}
$sreg_html = "";
$sreg = new Zend_OpenId_Extension_Sreg();
//若OpenID認證成功,取得OpenID Provider傳送回來的使用者資料
foreach (Zend_OpenId_Extension_Sreg::getSregProperties() as $prop) {
$val = isset($data[$prop]) ? $data[$prop] : "";
$sreg_html .= <<<EOF
<tr><td>$prop</td>
<td>
<input type="radio" name="$prop" value="required">
</td><td>
<input type="radio" name="$prop" value="optional">
</td><td>
<input type="radio" name="$prop" value="none" checked="1">
</td><td>
$val
</td></tr>
EOF;
}
//顯示使用者輸入OpenID進行登入,並選擇要向OpenID Provider取得個人資料項目的Form
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Zend OpenID Consumer Example</title>
<style>
input.openid_login {
background: url(login-bg.gif) no-repeat;
background-color: #fff;
background-position: 0 50%;
color: #000;
padding-left: 18px;
width: 220px;
margin-right: 10px;
}
</style>
</head>
<body>
<?php echo "$status<br>\n";?>
<div>
<form action="<?php echo Zend_OpenId::selfUrl(); ?>"
method="post" onsubmit="this.login.disabled=true;">
<fieldset id="openid">
<legend>OpenID Login</legend>
<input type="hidden" name="openid_action" value="login">
<div>
<input type="text" name="openid_identifier" class="openid_login" value="<?php echo $id;?>">
<input type="submit" name="login" value="login">
<table border="0" cellpadding="2" cellspacing="2">
<tr><td>&nbsp;</td><td>requird</td><td>optional</td><td>none</td><td>&nbsp</td></tr>
<?php echo "$sreg_html<br>\n";?>
</table>
<br>
<a href="<?php echo dirname(Zend_OpenId::selfUrl()); ?>/test_server.php?openid.action=register">register</a>
</div>
</fieldset>
</form>
</div>
</body>
</html>

<< test_server.php範例程式說明 >>

<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_OpenId
* @subpackage Demos
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/*
樣板頁面檔案說明

Client端以OpenID identity方式連線時回覆顯示的樣板頁面。
templates/identity.phtml

Client端以OpenID 2.0 identity方式連線時回覆顯示的樣板頁面。
templates/identity2.phtml

OpenID登入認證顯示的樣板頁面。
!!注意!!
僅針對執行test_server.php範例程式註冊成功的OpenID帳號才能進行登入
templates/login.phtml

用戶使用OpenID登入成功顯示的樣板頁面。
templates/profile.phtml

註冊成功後顯示的樣板頁面。
templates/registration_complete.phtml

用戶註冊顯示的樣板頁面。
templates/register.phtml

OpenID認證網站將使用者重導回OpenID Provider,要使用者選擇認證方式時顯示的樣板頁面。
templates/trust.phtml
*/
$dir = realpath(dirname(__FILE__)."/../../..");
set_include_path("$dir/library" . PATH_SEPARATOR . get_include_path());

/**
* @see Zend_OpenId_Provider
*/
require_once "Zend/OpenId/Provider.php";

/**
* @see Zend_OpenId_Extension_Sreg
*/
require_once "Zend/OpenId/Extension/Sreg.php";

/**
* @see Zend_Session_Namespace
*/
require_once "Zend/Session/Namespace.php";

$server = new Zend_OpenId_Provider();

/**
* trust_form
*
* @param string $site
* @param array|boolean $trusted
* @return string
*/
//用戶在其他支援OpenID認證網站進行登入
//重導回OpenID Provider時,用戶選擇認證方式的顯示頁面
function trust_form($site, $trusted) {
if (is_array($trusted)) {
$str = "";
if (isset($trusted['Zend_OpenId_Extension_Sreg'])) {
$trusted = $trusted['Zend_OpenId_Extension_Sreg'];
foreach ($trusted as $key => $val) {
$str .= "$key:\"$val\";";
}
}
$trusted = true;
}
$s = '<form method="POST">'
. '<tr><td>'
. '<input type="hidden" name="openid_action" value="trust">'
. '<input type="hidden" name="site" value="' . $site . '">'
. $site
// . '</td><td>'
// . ($trusted ? 'allowed' : 'denied')
. '</td><td>'
. ($trusted ?
'<input type="submit" style="width:100px" name="deny" value="Deny">' :
'<input type="submit" style="width:100px" name="allow" value="Allow">')
. '</td><td>'
. '<input type="submit" style="width:100px" name="del" value="Del">'
. '</td><td>'.$str.'</td></tr>'
. '</form>';
return $s;
}

/**
* sreg_form
*
* @param Zend_OpenId_Extension_Sreg $sreg
* @return string
*/
/*
當OpenID認證網站向OpenID Provider請求取得使用者個人資料時,
顯示此頁面讓使用者填寫個人資料
OpenID認證網站特別要求需要(requird)的資料欄位名稱部份會特別加上底線符號
*/
function sreg_form(Zend_OpenId_Extension_Sreg $sreg)
{
$s = "";
$props = $sreg->getProperties();
if (is_array($props) && count($props) > 0) {
$s = 'It also requests additinal information about you';
$s .= ' (fields marked by <u>*</u> are required)<br>';
$s .= '<table border="0" cellspacing="2" cellpadding="2">';
foreach ($props as $prop => $val) {
if ($val) {
$s .= '<tr><td><u>'.$prop.':*</u></td>';
} else {
$s .= '<tr><td>'.$prop.':</u></td>';
}
$value = "";
$s .= '<td><input type="text" name="openid.sreg.'.$prop.'" value="'.$value.'"></td></tr>';
}
$s .= '</table><br>';
$policy = $sreg->getPolicyUrl();
if (!empty($policy)) {
$s .= 'The private policy can be found at <a href="'.$policy.'">'.$policy.'</a>.<br>';
}
}
return $s;
}

$session = new Zend_Session_Namespace("opeinid.server");
Zend_Session::start();

$ret = false;
if ($_SERVER["REQUEST_METHOD"] == "GET") {
if (!isset($_GET['openid_action']) && isset($_GET['openid_mode'])) {
$ret = $server->handle($_GET, new Zend_OpenId_Extension_Sreg());
} else {
require_once 'Zend/View.php';

$view = new Zend_View();
//設定樣板頁面放置路徑
$view->setScriptPath(dirname(__FILE__) . '/templates');
$view->strictVars(true);

if (isset($session->id)) {
$view->id = $session->id;
}
if (isset($session->error)) {
$view->error = $session->error;
unset($session->error);
}
if (isset($_GET['openid_action'])) {
//用戶進行註冊,顯示註冊頁面
if ($_GET['openid_action'] == 'register') {
$ret = $view->render('register.phtml');
//用戶註冊成功,並顯示測試用之OpenID帳號
} else if ($_GET['openid_action'] == 'registration_complete' &&
isset($_GET['openid_name'])) {
$view->name = $_GET['openid_name'];
$view->url = Zend_OpenId::selfURL() . '?openid=' . $view->name;
if ($server->hasUser($view->url)) {
$view->url2 = Zend_OpenId::selfURL() . '?openid2=' . $view->name;
$ret = $view->render('registration_complete.phtml');
}
//用戶使用OpenID登入成功後進行Logout動作
} else if ($_GET['openid_action'] == 'logout') {
$server->logout();
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
/*
當用戶登入OpenID認證網站重導回OpenID Provier網站進行認證工作,
但用戶並未登入OpenID Provider時,會顯示登入頁面要求用戶先進行登入動作。
!!注意!!
僅針對執行test_server.php範例程式註冊成功的OpenID帳號才能進行登入
*/
} else if ($_GET['openid_action'] == 'login') {
if (isset($_GET['openid_identity'])) {
$view->id = $_GET['openid_identity'];
$view->ro = true;
}
$ret = $view->render('login.phtml');
} else if ($_GET['openid_action'] == 'trust') {
if ($server->getLoggedInUser() !== false) {
$view->site = $server->getSiteRoot($_GET);
$view->url = $server->getLoggedInUser();
$sreg = new Zend_OpenId_Extension_Sreg();
$sreg->parseRequest($_GET);
//額外顯示讓使用者填寫個人資料的頁面
$view->sreg = sreg_form($sreg);
//要使用者選擇認證方式的頁面
if ($server->hasUser($view->url)) {
$ret = $view->render('trust.phtml');
}
}
}
//Client端以OpenID identity方式連線時回覆的頁面
} else if (isset($_GET['openid'])) {
$url = Zend_OpenId::selfURL() . '?openid=' . $_GET['openid'];
if ($server->hasUser($url)) {
$view->server = Zend_OpenId::selfURL();
$view->name = $_GET['openid'];
$ret = $view->render('identity.phtml');
}
//Client端以OpenID 2.0 identity方式連線時回覆的頁面
} else if (isset($_GET['openid2'])) {
$url = Zend_OpenId::selfURL() . '?openid=' . $_GET['openid2'];
if ($server->hasUser($url)) {
$view->server = Zend_OpenId::selfURL();
$view->name = $_GET['openid2'];
$ret = $view->render('identity2.phtml');
}
} else {
//用戶使用OpenID登入成功顯示頁面
if ($server->getLoggedInUser() !== false) {
$view->url = $server->getLoggedInUser();
if ($server->hasUser($view->url)) {
$sites = $server->getTrustedSites();
$s = "";
foreach ($sites as $site => $trusted) {
if (is_bool($trusted) || is_array($trusted)) {
$s .= trust_form($site, $trusted);
}
}
if (empty($s)) {
$s = "<tr><td>None</td></tr>";
}
$view->sites = $s;
$ret = $view->render('profile.phtml');
}
/*首次造訪顯示登入頁面
!!注意!!
僅針對執行test_server.php範例程式註冊成功的OpenID帳號才能進行登入
*/
} else {
$ret = $view->render('login.phtml');
}
}
}
} else if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!isset($_POST['openid_action']) && isset($_POST['openid_mode'])) {
$ret = $server->handle($_POST, new Zend_OpenId_Extension_Sreg());
} else if (isset($_POST['openid_action'])) {
if ($_POST['openid_action'] == 'login' &&
isset($_POST['openid_url']) &&
isset($_POST['openid_password'])) {
if (!$server->login($_POST['openid_url'],
$_POST['openid_password'])) {
$session->error = 'Wrong identity/password!';
$session->id = $_POST['openid_url'];
}
unset($_GET['openid_action']);
Zend_OpenId::redirect($_SERVER['PHP_SELF'], $_GET);
//進行用戶註冊處理程序
} else if ($_POST['openid_action'] == 'register' &&
isset($_POST['openid_name']) &&
isset($_POST['openid_password']) &&
isset($_POST['openid_password2'])) {

$url = Zend_OpenId::selfURL() . '?openid=' . $_POST['openid_name'];
//用戶輸入的密碼與確認密碼不同
if ($_POST['openid_password'] != $_POST['openid_password2']) {
$session->name = $_POST['openid_name'];
$session->error = 'Password mismatch.';
header('Location: ' . $_SERVER['PHP_SELF'] . '?openid.action=register');
//進行新增用戶程序
} else if ($server->register($url, $_POST['openid_password'])) {
header('Location: ' . $_SERVER['PHP_SELF'] . '?openid.action=registration_complete&openid.name=' . $_POST['openid_name']);
//用戶註冊失敗,有可能是用戶登錄名稱已經存在
} else {
$session->error = 'Registration failed. Try another name.';
header('Location: ' . $_SERVER['PHP_SELF'] . '?openid.action=register');
}
exit;
//OpenID Provider根據用戶選擇的認證方式來處理後續與OpenID認證網站之間的互動工作
} else if ($_POST['openid_action'] == 'trust') {
if (isset($_GET['openid_return_to'])) {
$sreg = new Zend_OpenId_Extension_Sreg();
$sreg->parseResponse($_POST);
if (isset($_POST['allow'])) {
if (isset($_POST['forever'])) {
$server->allowSite($server->getSiteRoot($_GET), $sreg);
}
unset($_GET['openid_action']);
$server->respondToConsumer($_GET, $sreg);
} else if (isset($_POST['deny'])) {
if (isset($_POST['forever'])) {
$server->denySite($server->getSiteRoot($_GET));
}
Zend_OpenId::redirect($_GET['openid_return_to'], array('openid.mode'=>'cancel'));
}
} else if (isset($_POST['allow'])) {
$server->allowSite($_POST['site']);
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
} else if (isset($_POST['deny'])) {
$server->denySite($_POST['site']);
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
} else if (isset($_POST['del'])) {
$server->delSite($_POST['site']);
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
}
}
}
}
//判斷$ret有無資料,若有顯示$ret所包含頁面資料
if (is_string($ret)) {
echo $ret;
} else if ($ret !== true) {
header('HTTP/1.0 403 Forbidden');
echo 'Forbidden';
}

【下列文章您可能也有興趣】

沒有留言: