一步一步搭建 OAuth 認證服務器


http://www.fising.cn/2011/03/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E6%90%AD%E5%BB%BA-oauth-%E8%AE%A4%E8%AF%81%E6%9C%8D%E5%8A%A1%E5%99%A8.shtml

http://blog.csdn.net/newjueqi/article/details/7845282

http://www.open-open.com/lib/view/open1392863557428.html

http://justcoding.iteye.com/blog/1950270

http://oauth.net/documentation/getting-started/

https://code.google.com/archive/p/oauth-php/

Bug:

源碼包庫文件OAuthRequestSigner.php有bug

function getQueryString ( $oauth_as_header = true )
{
...
if ( !$oauth_as_header
|| (strncmp($name, 'oauth_', 6) != 0&&(應該為||) strncmp($name, 'xoauth_', 7) != 0))

 

現在越來越多開放的互聯網公司提供對外的 API 接口,使得第三方應用開發人員可以開發基於該平台接口的應用程序。國外有TwitterFlicker Service等;國內的,像騰訊微博開放平台新浪微博開放平台等等。

這些平台接口的認證方式,無一例外的,都采取了 OAuth 來實現(Twitter原來使用的是Basic Auth方式,后來全面轉向OAuth)。

那么,OAuth 是什么?OAuth認證又有什么好處呢?

OAuth 是什么

關於OAuth的定義,在 OAuth官網 的首頁上,有一行大大的文字說明:

(OAuth) 是一個開放協議,它以一種簡單、標准的方式實現對桌面和 Web 的應用程序的安全 API 認證。

OAuth 1.0 協議(中文版 | 英文版)這樣介紹OAuth:“OAuth 協議致力於使網站和應用程序(統稱為消費方)能夠在無須用戶透露其認證證書的情況下,通過 API 訪問某個web服務(統稱為服務提供方)的受保護資源。更一般地說,OAuth 為 API 認證提供了一個可自由實現且通用的方法”。

關於 OAuth 的用途,OAuth 1.0 協議(中文版 | 英文版)上舉了一個例子:某打印服務提供商 printer.example.com(消費方),希望在無須用戶提供其照片存儲站點密碼的情況下,訪問用戶儲存在 photos.example.net(服務提供方)上的個人照片。

假如沒有 OAuth,用戶必須要向消費方也就是 printer 提供自己在服務提供商 photos 上的授權資料(通常是密碼),消費方利用這個授權資料,通過服務提供方的權限驗證,從而獲得要打印的圖片。這樣看似沒有什么問題。但是用戶的授權資料,通常在這一過程中被消費方有意或者無意地竊取或泄露,從而對用戶和服務提供方的信息安全造成威脅。

而如果利用 OAuth 進行此過程的授權,用戶的授權資料並不會傳遞給第三方(也就是消費方,通常是App應用),而消費方只需要將用戶引導至服務提供方的授權頁面進行授權,使得消費方獲得訪問受限資源的權限即可。而在此過程中,用戶授權過程是在服務提供方進行的,消費方並不會直接接觸到用戶的授權資料,因此一般不會造成用戶授權資料的泄密,從而既保證了用戶和服務提供方的信息安全,又使得消費方完成了對受限資源的讀取。可謂一舉三得。

個人對 OAuth 授權過程的理解:服務提供方 SP 好比一個封閉院子,只有持卡人才能進入,用戶 U 就是持卡人之一。而消費方 C 沒有持卡,通常情況下是不能進入的。但是有一天,由於特殊原因,U 需要 C 幫忙去 SP 那里取一樣東西。這個時候問題就來了:  C 沒有持卡,不能進去院子,而 U 又不能把卡直接給 C (卡上面有很多個人機密信息,不方便外泄哦)。怎么辦呢?

哦,對了,U 可以帶着 C 去門口,告訴SP:這個人是我認識的,他需要進去幫我拿我的一樣東西,請予放行。這樣,U 既不用將帶有個人私密信息的門卡交給 C,C 也通過驗證拿到了屬於 U 的東西。

有的人要問了,是不是下次 C 想要再進 SP 的拿 U 的東西的話,是不是就不用 U 的指引了呢?人類社會的情況通常是這樣的。可惜,在 HTTP 的世界里,由於 HTTP 是無狀態的協議,因此,SP 仍然不會認識 C。所以,每次 C 想要取東西,總是需要 U 的指引。是不是很麻煩呢?呵呵。但是為了安全,麻煩一點又有什何妨!

上面介紹了 OAuth 認證的基本思路,如果你還不理解,可以參考 OAuth認證流程圖, 或者查看騰訊微博關於OAuth認證的介紹。OAuth 官方網站就有一篇文檔教程《OAuth入門指南》,不過沒有中文版本。有興趣同學的也可以自己看看。

OAuth 認證授權有以下幾個特點:

  • 1. 簡單:不管是 OAuth 服務提供者還是應用開發者,都很容易於理解與使用;
  • 2. 安全:沒有涉及到用戶密鑰等信息,更安全更靈活;
  • 3. 開放:任何服務提供商都可以實現 OAuth,任何軟件開發商都可以使用 OAuth;

那么下面我們就作為服務提供商角色,來實現 OAuth 認證服務器的安裝和搭建。

其實,很多先行者已經開發出了很多的 OAuth 消費方代碼(客戶端)和服務提供方代碼(服務端),這里是它們的一些列表,其中包含了 .NET (C#/VB.NET), ColdFusion, Java, Javascript, Jifty, Objective-C, OCaml, Perl, PHP, Python, Ruby, Erlang 和其他語言的一些實現。

通過 Google,我找到了一個開源的 OAuth 服務端代碼和消費方開源代碼庫項目——oauth-php. 我們就借此來實現。關於OAuth,項目主頁的介紹是: OAuth Consumer And Server Library For PHP. 它包含一個完整實現的可擴展的OAuth存儲,支持 MySQL/MySQLi,  Postgresql,  PDO 和 Oracle 等多種存儲方式。

它實現了以下方法:

  • 認證進來的請求
  • 為出去的請求簽名
  • 使用 body 為請求簽名
  • 為多用戶管理消費方的 key 和 token(服務端和消費端)
  • 記錄經過類庫處理的進出的請求(可以在數據庫中進行可選配置)

很多網站都在使用oauth-php, 包括荷蘭阿姆斯特丹Mediamatic Lab實驗室出品的anyMeta CMS. 目前,oauth-php 的代碼主要由Corollarium Technologies 負責維護。

為你的服務器增加 OAuth 非常簡單。你需要檢查進來的請求中 OAuth 認證細節。首先,我們需要四個控制器 controller 文件:

  • oauth_register.php 使消費方用戶獲得 key 和密鑰
  • request_token.php 返回一個未認證的 request token
  • authorize.php 認證一個request token
  • access_token.php 將認證后的 request token 置換為 access token

以下的例子,假設使用的數據存儲器是MySQL。你也可以使用其他數據庫——當你第一次使用 OAuthStore 實例的時候指定一個參數,告訴它你要使用的數據庫。

這就是假設在存儲器目錄,你有一個名為 OAuthStoremystore.php 文件。在這里我們使用 OAuthStoreMySQL.php 文件來實現。這也就是說,我們在實例化 OAuthStore 的時候,需要這樣做:

然后,在每個請求被處理之前,都可以檢查其是否帶有 OAuth 認證信息:

每個消費方都使用 key 和密鑰的組合和 token 和 token 密鑰的組合來為它的請求進行簽名。而在此之前,消費方必須要先獲取屬於它的消費方 key 和消費方密鑰。 oauth_register.php 就是負責分發消費方 key 和密鑰的控制器文件。

如果你想要更新之前注冊的消費方身份,提供消費方id,key 和 secret 。key 和 secret 在更新操作完成之前不會進行改變。

你還可以請求一個特定用戶注冊的所有消費方列表:

request_token.php 這個控制器文件負責返回請求 token(未認證的 request token)。當消費方獲取了 key 和 secret 之后,它就可以向服務器端請求未認證的 request token 了:

authorize.php 控制器文件負責認證一個用戶請求 token。這個控制器負責詢問用戶是否允許消費方訪問他的賬戶。如果允許,那么消費方將可以使用 request token 換取 access token。必須要保證用戶在訪問下面的代碼之前是登錄狀態。OAuthServer 服務器使用 SESSION 存儲一些 OAuth 狀態信息,所以必須要開啟seesion會話(要么是 session_start 函數,要么就是自動開啟)。

access_token.php 控制器文件負責將認證的request token換成access token。access token 可以被用來為請求簽名。

看完本文,如果還是一頭霧水,不知道如何下手,可以繼續閱讀《基於PHP & MySQL 搭建 OAuth Server》。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM