為了方便理解,可以先看一下在 OAuth 認證過程中的幾個關鍵術語,這也是 RFC5849 中 「1.1. Terminology」 小節的內容。也可以查看其中文版本。

 

想了一下,沒有想到好的應用場景,乾脆就使用 RFC5849 中的例子吧。這個例子大概的意思是:

 

Jane (使用者,資源的擁有者) 將自己度假的照片 (受保護資源) 上傳到了圖片分享網站A (服務提供者).
她現在想要在另外一個網站B (Client, 消費方) 線上列印這些照片. 一般情況下, Jane 需要使用自己的使用者名和密碼登陸網站A.
但是, Jane 並不希望將自己的使用者名和密碼洩露給網站B. 可是網站B需要訪問圖片分享網站A的圖片並將其列印出來.

 

首先,我們再虛擬機器上面搭建三個虛擬主機。我這裡搭建的三個主機是:

 

# 服務提供者 Service Provider 服務提供伺服器, 提供受保護資源
www.service.com
# 服務提供者 Service Provider OAuth認證伺服器,進行請求認證
auth.service.com
# 消費方 Consumer 客戶應用伺服器, 用來發起認證請求
www.demo.com

 

配合上面介紹的應用場景,www.service.com 相當於網站A,而 www.demo.com 則相當於網站B.

 

接下來,我們為網站 A 虛擬一個使用者 Jane,並將其使用者名和密碼以及她的照片保存在 MySQL 資料庫中。

 

先創建一個資料庫,名曰:photo, 在其中新建一個表user:

 

CREATE DATABASE `photo`;
CREATE TABLE IF NOT EXISTS `user` (
`userId` int(11) unsigned NOT Null AUTO_INCREMENT COMMENT '使用者ID',
`userName` Varchar(20) NOT Null COMMENT '使用者名',
`password` char(32) NOT Null COMMENT '會員密碼',
PRIMARY KEY (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者資訊表' AUTO_INCREMENT=1 ;

 

使用者有了,現在給使用者創建一個表,用來存儲使用者照片。新建一個表「image」:

 

CREATE TABLE IF NOT EXISTS `image` (
`imageId` int(11) unsigned NOT Null AUTO_INCREMENT COMMENT '圖片Id',
`userId` int(11) unsigned NOT Null COMMENT '使用者Id',
`imagePath` Varchar(255) NOT Null COMMENT '圖片路徑',
PRIMARY KEY (`imageId`),
KEY `userId` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='圖片表' AUTO_INCREMENT=1 ;

 

資料表有了,現在填充一些資料:

 

INSERTINTO`photo`.`user` (
`userId` ,
`userName` ,
`password`
)
VALUES (
'1','jane', MD5('123456')
);
INSERTINTO`photo`.`image` (
`imageId` ,
`userId` ,
`imagePath`
)
VALUES (
Null ,'1','path/to/jane/image.jpeg'
);

 

由於 auth.service.com 認證伺服器需要提供應用程式認證服務,所以需要創建一個表存儲應用程式資訊。實際上,還需要一些其他的相關的資料表。

 

 
我們這裡使用的是 MySQL 資料庫,打開瀏覽器,訪問 HTTP://auth.service.com/oauth-php/library/store/mysql/install.php 來進行資料表的安裝。事先需要編輯 install.php 進行資料庫配置。安裝完畢,請將該檔的資料庫連接部分重新注釋掉。

 

下面來實現OAUTH伺服器端的應用註冊功能。

 

首先在 oauth.service.com 伺服器下新建一個 config.inc.php 檔,檔內容如下:
<?php
// 資料庫連接資訊
$dbOptions = array(
'server' => 'localhost',
'username' => 'root',
'password' => '123456',
'database' => 'photo'
);
?>

 

該檔的主要作用是保存資料庫連接資訊。然後繼續新建一個 「oauth_register.php」 檔,檔內容如下:
<?php
// 當前登錄使用者
$user_id = 1;
// 來自使用者表單
$consumer = array(
// 下面兩項必填
'requester_name' => 'Fising',
'requester_email' => 'Fising@qq.com',
// 以下均為可選
'callback_uri' => 'HTTP://www.demo.com/oauth_callback',
'application_uri' => 'HTTP://www.demo.com/',
'application_title' => 'Online Printer',
'application_descr' => 'Online Print Your Photoes',
'application_notes' => 'Online Printer',
'application_type' => 'website',
'application_commercial' => 0
);
include_once 'config.inc.php';
include_once 'oauth-php/library/OAuthStore.php';
// 註冊消費方
$store = OAuthStore::instance('MySQL', $dbOptions);
$key = $store->updateConsumer($consumer, $user_id);
// 獲取消費方資訊
$consumer = $store->getConsumer($key, $user_id);
// 消費方註冊後得到的 App Key 和 App Secret
$consumer_id = $consumer['id'];
$consumer_key = $consumer['consumer_key'];
$consumer_secret = $consumer['consumer_secret'];
// 輸出給消費方
echo 'Your App Key: ' . $consumer_key;
echo '<br />';
echo 'Your App Secret: ' . $consumer_secret;
?>

 

這時候,通過瀏覽器訪問:HTTP://auth.service.com 就可以自動註冊一個應用(其實就是一個消費方Client)。並且將該應用的 App Key 和 App Secret呈現給你。下面 www.demo.com 網站將使用這2個字串進行認證。所以現在先把這兩個值保存起來備用。

 

看到的頁面應該類似于:

 

Your App Key: de94eb65317c0d7a00af1261fc26882c04df0f850
Your App Secret: 7769ae71e703509a92c7f3816a9268af

 

這樣,消費方註冊功能就完成了。

 

接下來,消費方 www.demo.com 就可以使用這個 App Key 和 App Secret,向認證伺服器請求未授權的 Request token 了。這一步需要做兩件事情:① 消費方 www.demo.com 向 OAuth Server 也就是 auth.service.com 請求未授權的 Request token;② OAuth Server 處理消費方的請求,生成並將未授權的 Request token 返回給消費方;

 

先來實現第②件任務。

 

在認證伺服器 auth.service.com 的根目錄下新建一個檔」request_token.php」, 檔內容是:

 

<?php
include_once 'config.inc.php';
include_once 'oauth-php/library/OAuthStore.php';
include_once 'oauth-php/library/OAuthServer.php';
$store = OAuthStore::instance('MySQL', $dbOptions);
$server = new OAuthServer();
$server->requestToken();
exit();
?>

 

現在認證伺服器已經可以回應消費方請求「未授權的token」了。

 

這裡要特別注意一點,如果測試的時候,消費方和服務提供者在同一台伺服器,就像我現在的情況,三個伺服器都在同一個虛擬機器裡,那麼要注意,用戶端請求的時候,可能發生找不到主機的問題。為啥?因為伺服器找不到虛擬的 auth.service.com 認證伺服器。怎麼解決呢?

 

Windows下面,我們可以設置 hosts 主機表檔,使某一功能變數名稱的指向某一固定IP位址。Linux下面也有類似的主機表檔,它的位置是 /etc/hosts,接下來如何做,這裡就不用講啦。

 

現在來實現第①件任務。

 

首先在消費方資料庫伺服器將認證伺服器添加到消費方的 OAuthStore 中。這裡的資料庫安裝方式與服務方相同,不再贅述。

 

然後,我們再消費方伺服器 www.demo.com 的根目錄添加一個 「config.inc.php」 檔,保存消費方自己的資料庫連接資訊。我這裡由於使用的是虛擬主機,恰好消費方和認證伺服器的資料庫連接參數是一樣的。實際情況可能不是這樣。檔的內容與上面的類似:
<?php
// 資料庫連接資訊
$dbOptions = array(
'server' => 'localhost',
'username' => 'root',
'password' => '123456',
'database' => 'photo'
);
?>

 

然後,在消費方伺服器根目錄繼續添加一個檔,add_server.php, 用來向消費方的資料庫中存儲認證伺服器的資訊。其實一般的,這個資訊可能會直接寫在設定檔裡,不過,oauth-php提供了更加強大的資料庫的存儲方案而已。該檔的內容是:
 
<?php
include_once 'config.inc.php';
include_once 'oauth-php/library/OAuthStore.php';
$store = OAuthStore::instance('MySQL', $dbOptions);
// 當前使用者的ID, 必須為整數
$user_id = 1;
// 伺服器描述資訊
$server = array(
'consumer_key' => 'de94eb65317c0d7a00af1261fc26882c04df0f850',
'consumer_secret' => '7769ae71e703509a92c7f3816a9268af',
'server_uri' => 'HTTP://auth.service.com/',
'signature_methods' => array('HMAC-SHA1', 'PLAINTEXT'),
'request_token_uri' => 'HTTP://auth.service.com/request_token.php',
'authorize_uri' => 'HTTP://auth.service.com/authorize.php',
'access_token_uri' => 'HTTP://auth.service.com/access_token.php'
);
// 將伺服器資訊保存在 OAuthStore 中
$consumer_key = $store->updateServer($server, $user_id);
?>
 
這樣,通過瀏覽器訪問一下該檔,HTTP://www.demo.com/add_server.php, 伺服器的相關資訊就會被保存起來了。用於生產環節時,這裡可能是一個簡單的管理系統,可以用來管理認證伺服器清單。注意,上面檔裡的 key 和 secret 正是我們之前在認證伺服器 HTTP://auth.service.com 註冊消費方應用時得到的。
 
有了認證伺服器的相關資訊,我們現在可以去獲取「未認證的token」了。在 www.demo.com 根目錄新建一個檔 index.php:
 
 
<?php
if(isset($_GET['req']) && ($_GET['req'] == 1)){
include_once 'config.inc.php';
include_once 'oauth-php/library/OAuthStore.php';
include_once 'oauth-php/library/OAuthRequester.php';
$store = OAuthStore::instance('MySQL', $dbOptions);
// 使用者Id, 必須為整型
$user_id = 1;
// 消費者key
$consumer_key = '286cec927c4c5482e75d80759e9fdd8904df10e2f';
// 從伺服器獲取未授權的token
$token = OAuthRequester::requestRequestToken($consumer_key, $user_id);
var_dump($token);
die();
}
else{
?>
<!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>測試頁面</title>
</head>
<body>
<p>消費放測試頁面,點擊下面的按鈕開始測試</p>
<input type="button" name="button" value="Click Me" id="RequestBtn"/>
<script type="text/javascript">
document.getElementById('RequestBtn').onclick = function(){
window.location = 'index.php?req=1';
}
</script>
</body>
</html>
<?php
}
?>
 
現在,通過瀏覽器訪問 www.demo.com/index.php頁面,然後點擊頁面上的「Click Me」按鈕,開始向auth.service.com伺服器請求「未授權的token」。如果最後結果顯示類似于:
 
1 array(2) { ["authorize_uri"]=> string(37) "HTTP://auth.service.com/authorize.php" ["token"]=> string(41) "dc8e8df797d9737b0acfe7a8b549005604df5e485" }
 
那麼恭喜你,獲取「未授權的token」這一步,已經順利完成了。
 
接下來,根據 OAuth 驗證的流程,應該是重定向使用者瀏覽器到 auth.service.com 進行 token 授權。
 
在 auth.demo.com 伺服器根目錄新建一個檔 authorize.php, 代碼如下:


 
<?php
session_start();
if (empty($_SESSION['authorized']))
{
$uri = $_SERVER['REQUEST_URI'];
header('Location: /login.php?goto=' . urlencode($uri));
exit();
}
include_once 'config.inc.php';
include_once 'oauth-php/library/OAuthStore.php';
include_once 'oauth-php/library/OAuthServer.php';
//登陸使用者
$user_id = 1;
// 取得 oauth store 和 oauth server 物件
$store = OAuthStore::instance('MySQL', $dbOptions);
$server = new OAuthServer();
try
{
// 檢查當前請求中是否包含一個合法的請求token
// 返回一個陣列, 包含consumer key, consumer secret, token, token secret 和 token type.
$rs = $server->authorizeVerify();
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
// 判斷使用者是否點擊了 "allow" 按鈕(或者你可以自訂為其他標識)
$authorized = array_key_exists('allow', $_POST);
// 設置token的認證狀態(已經被認證或者尚未認證)
// 如果存在 oauth_callback 參數, 重定向到客戶(消費方)位址
$server->authorizeFinish($authorized, $user_id);
// 如果沒有 oauth_callback 參數, 顯示認證結果
// ** 你的代碼 **
}
else
{
echo 'Error';
}
}
catch (OAuthException $e)
{
// 請求中沒有包含token, 顯示一個使使用者可以輸入token以進行驗證的頁面
// ** 你的代碼 **
}
?>
 
如果使用者未登錄,則要求先行登陸才能進行授權操作。
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()