OAuth2.0 認證服務
安裝
你可以在github上下載OAuth Server PHP,也可以用下列命令下載,不過內容都是一樣的
mkdir my-oauth2-walkthrough cd my-oauth2-walkthrough git clone https://github.com/bshaffer/oauth2-server-php.git -b master
下載后放在根目錄,因為這只是個測試!
在這之后配置數據庫
Database: `oauth2db`
1 -- 2 -- Database: `oauth2db` 3 -- 4 5 -- -------------------------------------------------------- 6 7 -- 8 -- 表的結構 `oauth_access_tokens` 9 -- 10 11 CREATE TABLE IF NOT EXISTS `oauth_access_tokens` ( 12 `access_token` varchar(40) NOT NULL, 13 `client_id` varchar(80) NOT NULL, 14 `user_id` varchar(255) DEFAULT NULL, 15 `expires` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 16 `scope` varchar(2000) DEFAULT NULL 17 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 18 19 -- -------------------------------------------------------- 20 21 -- 22 -- 表的結構 `oauth_authorization_codes` 23 -- 24 25 CREATE TABLE IF NOT EXISTS `oauth_authorization_codes` ( 26 `authorization_code` varchar(40) NOT NULL, 27 `client_id` varchar(80) NOT NULL, 28 `user_id` varchar(255) DEFAULT NULL, 29 `redirect_uri` varchar(2000) DEFAULT NULL, 30 `expires` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 31 `scope` varchar(2000) DEFAULT NULL 32 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 33 34 -- -------------------------------------------------------- 35 36 -- 37 -- 表的結構 `oauth_clients` 38 -- 39 40 CREATE TABLE IF NOT EXISTS `oauth_clients` ( 41 `client_id` varchar(80) NOT NULL, 42 `client_secret` varchar(80) NOT NULL, 43 `redirect_uri` varchar(2000) NOT NULL, 44 `grant_types` varchar(80) DEFAULT NULL, 45 `scope` varchar(100) DEFAULT NULL, 46 `user_id` varchar(80) DEFAULT NULL 47 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 48 49 -- 50 -- 轉存表中的數據 `oauth_clients` 51 -- 52 53 INSERT INTO `oauth_clients` (`client_id`, `client_secret`, `redirect_uri`, `grant_types`, `scope`, `user_id`) VALUES 54 ('testclient', 'testpass', 'https://user.endv.cn/', 'authorization_code', '', ''); 55 56 -- -------------------------------------------------------- 57 58 -- 59 -- 表的結構 `oauth_jwt` 60 -- 61 62 CREATE TABLE IF NOT EXISTS `oauth_jwt` ( 63 `client_id` varchar(80) NOT NULL, 64 `subject` varchar(80) DEFAULT NULL, 65 `public_key` varchar(2000) DEFAULT NULL 66 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 67 68 -- -------------------------------------------------------- 69 70 -- 71 -- 表的結構 `oauth_refresh_tokens` 72 -- 73 74 CREATE TABLE IF NOT EXISTS `oauth_refresh_tokens` ( 75 `refresh_token` varchar(40) NOT NULL, 76 `client_id` varchar(80) NOT NULL, 77 `user_id` varchar(255) DEFAULT NULL, 78 `expires` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 79 `scope` varchar(2000) DEFAULT NULL 80 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 81 82 -- -------------------------------------------------------- 83 84 -- 85 -- 表的結構 `oauth_scopes` 86 -- 87 88 CREATE TABLE IF NOT EXISTS `oauth_scopes` ( 89 `scope` text, 90 `is_default` tinyint(1) DEFAULT NULL 91 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 92 93 -- -------------------------------------------------------- 94 95 -- 96 -- 表的結構 `oauth_users` 97 -- 98 99 CREATE TABLE IF NOT EXISTS `oauth_users` ( 100 `username` varchar(255) NOT NULL, 101 `password` varchar(2000) DEFAULT NULL, 102 `first_name` varchar(255) DEFAULT NULL, 103 `last_name` varchar(255) DEFAULT NULL 104 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我們來建立一個server.php文件來配置server,這個文件可以被所有的終端來調用。
1 <?php 2 /** 配置 */ 3 $dsn= 'mysql:dbname=test;host=localhost'; 4 $username = 'test'; 5 $password = 'test'; 6 7 // 錯誤報告(這畢竟是一個演示!) 8 ini_set('display_errors',1);error_reporting(E_ALL); 9 10 // 自動加載 11 require_once('oauth2-server-php/src/OAuth2/Autoloader.php'); 12 OAuth2\Autoloader::register(); 13 $storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password)); 14 15 // 通過存儲對象或對象數組存儲的oauth2服務器類 16 $server = new OAuth2\Server($storage); 17 18 // 授權碼 有效期只有30秒 19 $server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage)); 20 21 // 客戶端證書 22 $server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage)); 23 24 // 用戶憑據 25 $server->addGrantType(new OAuth2\GrantType\UserCredentials($storage)); 26 // 刷新令牌 啟用這個會報錯,原因未知 27 // $server->addGrantType(new OAuth2\GrantType\RefreshToken($refreshStorage))
記得配置數據庫的用戶名和密碼 test
Token控制器
下面,我們將建立一個Token控制器,這個控制器URI將會返回OAuth2的Token給客戶端
<?php // include our OAuth2 Server object require_once __DIR__.'/server.php'; $server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
測試Token控制器
需要先創建一條記錄,來注冊一個新的應用 (上面腳本中已插入,需要先刪除!)
INSERT INTO `oauth_clients` (`client_id`, `client_secret`, `redirect_uri`, `grant_types`, `scope`, `user_id`) VALUES
('testclient', 'testpass', 'https://user.endv.cn/', 'authorization_code', '', '');
然后用命令行調用
curl -u testclient:testpass https://user.endv.cn/token.php --data "grant_type=authorization_code&code=f8ef50221f7817f3e01d2d6c31a33f3c40db76a5"
這里的URL只是示例,實地操作要確定能找到這個token.php
如果運行正常,則顯示
{"access_token":"84c66d296308aad20aa5e065743d2fe30426b046","expires_in":3600,"token_type":"Bearer","scope":null,"refresh_token":"d49cd4d7d875065888fc457c7c714cab9fcf9d69"}
資源控制器的建立和測試
你創建了Token,你需要在API中測試它:
resource.php
<?php //資源控制器的建立和測試 require_once __DIR__.'/server.php'; if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) { $server->getResponse()->send(); die; } $token = $server->getAccessTokenData(OAuth2\Request::createFromGlobals()); echo "User ID associated with this token is {$token['user_id']}"; echo json_encode(array('success' => true, 'message' => '您訪問了我的API!'));
然后運行下面的命令,記得將YOUR_TOKEN替換成剛才得到的token,還有確保URL的正確
curl https://user.endv.cn/resource.php --data 'access_token=YOUR_TOKEN'
如果沒出問題,則會得到下面的結果
{"success":true,"message":"You accessed my APIs!"}
認證控制器的創建和測試
驗證控制器是OAuth2的殺手鐧,它允許你的平台幫助用戶驗證第三方應用
它不像第一個例子中直接返回一個Access Token,這里稍微復雜一點:
然后在瀏覽器中打開這個URL
https://user.endv.cn/authorize.php?response_type=code&client_id=testclient&state=xyz
你將會看到一個表單,當你選擇yes的時候會彈出你所獲得的Authorization Code
現在你可以用這個Authorization Code來剛才建立的token.php獲得TOKEN,命令如下
curl -u testclient:testpass https://user.endv.cn/token.php -d 'grant_type=authorization_code&code=YOUR_CODE'
就像剛才一樣,你獲得了一個TOKEN
{"access_token":"6f05ad622a3d32a5a81aee5d73a5826adb8cbf63","expires_in":3600,"token_type":"bearer","scope":null}
請在30秒內完成這個操作,因為Authorization Code的有效期只有30秒
用Access Token聯系本地用戶
當你認證了一個用戶並且分派了一個Token之后,你可能想知道彼時到底是哪個用戶使用了這個Token
你可以使用handleAuthorizeRequest的可選參數user_id來完成,修改你的authorize.php文件
$userid = 1234; // A value on your server that identifies the user $server->handleAuthorizeRequest($request, $response, $is_authorized, $userid)
這樣一來,用戶ID就伴隨Token一起存進數據庫了
當Token被客戶端使用的時候,你就知道是哪個用戶了,修改 resource.php 來完成任務
測試:點我測試


測試到此結束,后續客戶端的建立。
