基於PHP構建OAuth 2.0 服務端 認證平台


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;
View Code

 我們來建立一個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 來完成任務

測試:點我測試

 

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

 

 


 


免責聲明!

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



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