本年 8 月 16 日起,Twitter 官方不再支持基本身份認證協議(basic authentication protocol)。這意味着開發者唯一可以訪問 Twitter 的方法是利用 Twitter 的第三方應用。在本篇教程中,我會講解如何通過 PHP 來使用 Twitter 官方的一鍵登錄系統。
作者:Rafael Soto
原文鏈接:http://net.tutsplus.com/tutorials/php/how-to-authenticate-users-with-twitter-oauth/
第一步:創建應用
我們首先需要申請一個新的 Twitter 應用。
- 點擊這裏,在 dev.twitter.com 打開註冊新應用的表單;
- 根據你的需要添加表單中的各項內容,確認在應用類型(Application Type)那裏要選擇“瀏覽器(Browser)”,並設置一個回調地址(Callback URL),例如像 http://localhost.com/twitter_login.php 這樣的地址,(http://localhost/ 這樣的地址可不行,因爲不包含域名信息);
- 最後選擇讀和寫(Read & Write),並填寫驗證碼,點擊註冊應用(Register Application)按鈕來完成申請。
注意上圖的紅框,等一下我們將用到上圖中的 Consumer key 和 Consumer secret 信息。
網上已經有了不少現成的 Twitter 認證的類庫,可以簡化我們的工作。在 PHP 裏面我推薦 twitteroauth ,是比較好用的一個,如果你使用其它開發語言,可以在這裏找適合你的類庫。
請在下載到的壓縮包中找到名爲 twitteroauth 的目錄,將其部署到你的應用程序根目錄下。
在我們開始編碼前,我們還需要一張數據庫來保存用戶信息,下面是一個基本的 Mysql 的例子:
1 2 3 4 5 6 7 8 9 |
CREATE TABLE `users` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `oauth_provider` varchar(10), `oauth_uid` text, `oauth_token` text, `oauth_secret` text, `username` text, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; |
注意 oauth_token 和 oauth_secret 這兩個字段。Twitter 的 OAuth 認證需要 token 和 token_secret 兩個參數來完成認證,所以我們需要預留兩個字段來記錄他們。
第二步:註冊用戶
我們需要依次完成以下工作:
- 向 Twitter 發起認證申請
- 註冊/或者登錄,如果用戶已經有帳號的情況下
- 將相關數據保存在 Session 中
申請認證
基於 OAuth 的認證流程從生成一個網址開始。用戶被重定向到該網址要求認證,認證通過後,會重定向到我們的應用服務器,並會將兩個認證後的參數通過 URL 方式傳回。
準備好剛纔下載的類庫,初始化 Session,讓我們開始吧:
1 2 |
require("twitteroauth/twitteroauth.php"); session_start(); |
創建一個新的 TwitterOAuth 實例,傳入我們在第一步申請應用時獲取到的 consumer key 和 consumer secret。接下來我們準備發出認證請求,保存認證信息到 Session 中,然後重定向到 Twitter 網站進行認證。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// 創建 TwitterOAuth 對象實例 $twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET'); // Requesting authentication tokens, the parameter is the URL we will be redirected to $request_token = $twitteroauth->getRequestToken('http://localhost.com/twitter_oauth.php'); // 保存到 session 中 $_SESSION['oauth_token'] = $request_token['oauth_token']; $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; // 如果沒有錯誤發生 if($twitteroauth->http_code==200){ // Let's generate the URL and redirect $url = $twitteroauth->getAuthorizeURL($request_token['oauth_token']); header('Location: '. $url); } else { // 發生錯誤,你可以做一些更友好的處理 die('Something wrong happened.'); } |
將代碼保存爲 twitter_login.php, 然後訪問 http://localhost.com/twitter_login.php 進行測試,如果一切 OK 的話,你應該會被重定向到 twitter.com,你將看到如下畫面:
點擊允許(allow)按鈕,你將被重定向到 http://localhost.com/twitter_oauth.php — 這是我們在上段代碼裏設置過的,不過我們還沒創建這個文件,所以現在代碼會拋出一個錯誤。讓我們建立這個文件,記得要先加入包含類庫和初始化 Session 的代碼,就像我們第一個例子裏那樣。
接下來,我們還需要在這個文件中完成以下三件事:
- 驗證 URL 中的數據
- 驗證 Session 中的 token 數據
- 驗證 Session 中的 secret 數據
所以,首先要進行數據合法性的判斷:
1 2 3 4 5 6 |
if(!empty($_GET['oauth_verifier']) && !empty($_SESSION['oauth_token']) && !empty($_SESSION['oauth_token_secret'])){ // 數據合法,繼續 } else { // 數據不完整,轉到上一步 header('Location: twitter_login.php'); } |
如果所有數據庫都是合法的,我們需要創建一個新的 TwitterOAuth 對象實例,跟之前不同的是,我們要把獲取到的 token 數據做爲參數傳入對象。之後,我們應該可以獲取到一個 access token,這個獲取到的數據應該是一個數組,這個 access token 是我們唯一需要保存起來的數據,先來做一個簡單的測試吧:
1 2 3 4 5 6 7 8 9 10 |
// TwitterOAuth 對象實例,注意新加入的兩個參數 $twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); // 獲取 access token $access_token = $twitteroauth->getAccessToken($_GET['oauth_verifier']); // 將獲取到的 access token 保存到 Session 中 $_SESSION['access_token'] = $access_token; // 獲取用戶信息 $user_info = $twitteroauth->get('account/verify_credentials'); // 打印用戶信息 print_r($user_info); |
一切正常的話,上面的代碼會輸出用戶的資料。你可以通過 $user_info->id 來獲得用戶的 ID,通過 $user_info->screen_name 來獲取用戶名,等等,其它的信息也可以通過同樣的方式獲取。
需要重點指出的是,oauth_verifier 這個傳回來的參數不能被重用,如果上面的代碼已經正確輸出了用戶信息,你可以試着重新刷新頁面,應該會看到頁面會拋出一個錯誤信息,因爲 oauth_verifier 已經被我們用過一次了。要再次使用,需要到 twitter_login.php 頁面重新發起一個認證請求。
用戶註冊
獲得了用戶信息後,現在我們要開始把用戶信息註冊到我們自己的數據庫中,當然前提是用戶沒有在本地數據庫註冊過。首先要連接數據庫,代碼如下:
1 2 |
mysql_connect('localhost', 'YOUR_USERNAME', 'YOUR_PASSWORD'); mysql_select_db('YOUR_DATABASE'); |
上面代碼中的數據庫鏈接信息要改成你自己的。如果用戶已經存在於我們的數據庫中,我們需要更新用戶的 tokens 字段,因爲這說明 Twitter 生成了新的 tokens,數據庫中的 tokens 已經過期了。如果用戶不存在,我們需要新加一條記錄,並將相關的數據保存在 Session中,最後重定向回 twitter_update.php 頁面。相關代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
if(isset($user_info->error)){ // Something's wrong, go back to square 1 header('Location: twitter_login.php'); } else { // Let's find the user by its ID $query = mysql_query("SELECT * FROM users WHERE oauth_provider = 'twitter' AND oauth_uid = ". $user_info->id); $result = mysql_fetch_array($query); // If not, let's add it to the database if(empty($result)){ $query = mysql_query("INSERT INTO users (oauth_provider, oauth_uid, username, oauth_token, oauth_secret) VALUES ('twitter', {$user_info->id}, '{$user_info->screen_name}', '{$access_token['oauth_token']}', '{$access_token['oauth_token_secret']}')"); $query = mysql_query("SELECT * FROM users WHERE id = " . mysql_insert_id()); $result = mysql_fetch_array($query); } else { // Update the tokens $query = mysql_query("UPDATE users SET oauth_token = '{$access_token['oauth_token']}', oauth_secret = '{$access_token['oauth_token_secret']}' WHERE oauth_provider = 'twitter' AND oauth_uid = {$user_info->id}"); } $_SESSION['id'] = $result['id']; $_SESSION['username'] = $result['username']; $_SESSION['oauth_uid'] = $result['oauth_uid']; $_SESSION['oauth_provider'] = $result['oauth_provider']; $_SESSION['oauth_token'] = $result['oauth_token']; $_SESSION['oauth_secret'] = $result['oauth_secret']; header('Location: twitter_update.php'); } |
需要注意的是,上面代碼中的 SQL 沒有經過驗證,你在實際使用的時候可能要經過修改。連接數據庫前,我們需要先驗證一下用戶是否已經登錄:
1 2 3 4 |
if(!empty($_SESSION['username'])){ // User is logged in, redirect header('Location: twitter_update.php'); } |
有了用戶名,我們就可以展示一條個性的歡迎信息了:
1 |
<h2>Hello <?=(!empty($_SESSION['username']) ? '@' . $_SESSION['username'] : 'Guest'); ?></h2> |
Let’s get to the fun side: updating, following and reading.
第三步:獲取用戶狀態
Twitter 官方 API 提供了二十餘種資源供開發者使用,例如:timeline, tweets, users, trends, lists, direct messages, 等等。 每一種資源都有對應一堆的方法可供調用的,具體的用法和介紹可以參見官方文檔。我們這裏只實現最簡單的,其它的你可以舉一反三。
跟前兩步一樣,代碼開始前你要先創建對象實例,並初始化 Session。
1 2 3 |
if(!empty($_SESSION['username'])){ $twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', $_SESSION['oauth_token'], $_SESSION['oauth_secret']); } |
我們來試着獲取用戶的 timeline 數據,手冊告訴我們,資源的路徑是 statuses/home_timeline,手冊上的版本號和格式參數我們不需要關心,類庫已經幫我們自己完成了。
1 2 |
$home_timeline = $twitteroauth->get('statuses/home_timeline'); print_r($home_timeline); |
用上面的代碼,你應該可以獲取到正確的數據了。如果你願意,可以用一個 foreach 來循環展示具體的條目。手冊上關於 timeline 資源的說明中,還有一些參數可以供選擇的,例如每次獲取的條數。上面代碼的 get 方法有一個可選參數,你可以根據需要傳入相應的值。如果想獲取最新的 40 條數據,只需要使用下面的代碼:
1 |
$home_timeline = $twitteroauth->get('statuses/home_timeline', array('count' => 40)); |
當然,你可以獲取任何人的公開的 timeline 數據。使用 statues/user_timeline 資源即可,需要傳入要獲取用戶的用戶 ID 或用戶名。例如想獲取 @nettuts 的 timeline 數據,你需要下面的代碼:
1 |
$nettuts_timeline = $twitteroauth->get('statuses/user_timeline', array('screen_name' => 'nettuts')); |
看到了吧,只要授權通過,獲取這些 timeline 數據,只不過是小意思。
第四步:好友關係
通過好友關係,你可以檢查某個用戶是否是另一個用戶的關注者(Follows),當然也可以關注、或者取消關注指定的用戶,下面的代碼片斷用來檢查你是否是筆者的關注者,如果不是的話,則會自動關注筆者。
首先,讓我們先來看一下開發者手冊上關於 friendships/exists 和 friendships/create 的這部分說明。注意到了嗎?friendships/create 的調用方法是 POST,跟我們前面用的 GET 有些不同。當然,我們用的類庫中已經包含了一個叫 post() 的方法,使用起來跟之前的 get() 差不多,唯一不同的地方在於 get() 是用來獲取數據的,而 post() 一般用來更新、創建和刪除數據。
friendships/exists 需要傳入兩個參數:用戶A 和 用戶B。friendships/create 則只需要一個參數:用戶名(screen_name)或 用戶ID( user_id)。
1 2 3 4 5 |
$follows_faelazo = $twitteroauth->get('friendships/exists', array('user_a' => $_SESSION['username'], 'user_b' => 'faelazo')); if(!$follows_faelazo){ echo 'You are NOT following @faelazo!'; $twitteroauth->post('friendships/create', array('screen_name' => 'faelazo')); } |
同樣,你可以用類似的代碼來取消關注某個用戶,只需簡單的把 create 替換爲 destory:
1 2 3 4 5 |
$follows_faelazo = $twitteroauth->get('friendships/exists', array('user_a' => $_SESSION['username'], 'user_b' => 'faelazo')); if($follows_faelazo){ echo 'You are following @faelazo! Proceed to unfollow...'; $twitteroauth->post('friendships/destroy', array('screen_name' => 'faelazo')); } |
第五步:更新
This is probably the most interesting section, since it’s Twitter’s core: posting an update, as you might have imagined, is pretty straightforward. The path is statuses/update, the method is POST (since we are not reading), and the one required argument is status.
1 |
$twitteroauth->post('statuses/update', array('status' => 'Hello Nettuts+')); |
如果上面的代碼執行成功的,到你的 Twitter 頁面看下,你應該會看到類似的畫面:
讓我們試着轉發 @Nettut 的這條 twitter:the HTML 5 Competition,這條記錄的 ID 是 19706871538,手冊告訴我們,轉發需要調用的資源路徑是: statuses/retweet/:id, :id 即是我們要轉發的消息 ID,方法爲 POST,此方法不需要其它附加的參數。
$twitteroauth->post('statuses/retweet/19706871538');
要刪除某條消息,我們需要傳入要刪除的消息 ID,就像轉發的操作那樣,假設消息的 ID 爲 123456789,刪除這條消息的代碼如下:
1 |
$twitteroauth->post('statuses/destroy/123456789'); |
當然,上面刪除的代碼有個前提,只會刪除有經過我們授權的用戶消息。
小結
Twitter 的 API 很簡單,很容易讓人理解,甚至比 FaceBook 的文檔都容易得多。遺憾的是認證的過程需要繞一些彎子。
有一點需要特別提醒的是,如果你的應用得到了用戶的授權(你的應用有了讀寫權限),你基本上就相當於控制了這個用戶帳戶使用權。請小心使用你的權利,少做一些未經過用戶授權的事,這會給你製造不少麻煩。
Twitter 很快就會取締基本身份驗證模式(Basic Authentication),OAuth 是最終的解決方案。你現在就可以試着將本文學到的知識應用到你的網站上。讓用戶不用註冊,就可以用世界上最流行的網站帳號直接登錄,不也是一件很酷的事情嗎?