前奏javascript
系統:Ubuntu 語言:PHP7 框架:YAF OAuth2.0:bshaffer/oauth2-server-php
OAuth2.0
有不少開源代碼庫php
Github 排名前兩位css
thephpleague/oauth2-server bshaffer/oauth2-server-php
本文使用的是第二個:bshaffer
。緣由:使用簡單,能夠很快上手,文檔齊全,功能完善。html
wiki
: https://bshaffer.github.io/oa...github
: https://github.com/bshaffer/o...java
引入 OAuth2.0 的 Server 端源代碼node
編輯 Composer.json
文件mysql
{ "require": { "bshaffer/oauth2-server-php" : "v1.10.0" } }
yaf框架結構jquery
├── application │ └── modules │ └── User │ ├── controllers │ │ └── Oauth.php │ └── views │ └── oauth │ ├── authorize.php │ ├── auth.php │ ├── index.php │ └── resource.php ├── Bootstrap.php ├── cli ├── composer.json ├── composer.lock ├── composer.phar ├── conf ├── docs ├── public └── vendor
Yaf 框架中,在 Bootstrap.php
文件中自動加載 OAuth2.0
git
public function _initLoader(Yaf_Dispatcher $dispatcher) { include(APP_PATH . '/vendor/autoload.php'); }
新建一個 Controller 文件:Oauth.php
,在裏面創建幾個 Actiongithub
AuthorizeAction() 服務端:提供受權 TokenAction() 服務端:提供Token ResourceAction() 服務端:提供資源 IndexAction() 客戶端:模擬第三方接入 _server() 服務端:初始化服務器相關,如:存儲,這裏採用mysql
命名空間
use OAuth2\Server; use OAuth2\Storage\Pdo; use OAuth2\GrantType\AuthorizationCode; use OAuth2\GrantType\ClientCredentials; use OAuth2\GrantType\UserCredentials; use OAuth2\Request; use OAuth2\Response;
_server() 函數代碼
private function _server() { $dbParams = array( 'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=oauth;charset=utf8;', 'username' => 'root', 'password' => '123456', ); // $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost" $storage = new Pdo($dbParams); // Pass a storage object or array of storage objects to the OAuth2 server class $server = new Server($storage); // Add the "Client Credentials" grant type (it is the simplest of the grant types) $server->addGrantType(new ClientCredentials($storage)); // Add the "Authorization Code" grant type (this is where the oauth magic happens) $server->addGrantType(new AuthorizationCode($storage)); return $server; }
IndexAction() 代碼
public function indexAction() { $uri = $_SERVER['QUERY_STRING']; $code = substr($uri, strpos($uri, 'code=')+5, 40); $state = substr($uri, strpos($uri, 'state=')+6); if ($code) { $params = array( 'code' => $code, 'state' => $state, 'client_id' => 'client_id', 'client_secret' => 'client_secret', 'grant_type' => 'authorization_code', 'scope' => 'basic', 'redirect_uri' => 'http://yourhost/user/oauth/index', ); $url = 'http://yourhost/user/oauth/token'; $result = $this->httpPost($url, $params); $result = json_decode($result, true); //寫入Session,便於測試 Yaf_Session::getInstance()->set('access_token',$result['access_token']); return false; } else { //客戶端請求受權以前,頁面中展現一個連接,用戶點後,能夠跳轉至服務端的受權頁面。 $this->getView()->assign('data', array())->render('oauth/index.php'); } }
對應的模板代碼:oauth/index.php
<div> <a href="http://yourhost/User/Oauth/Authorize?response_type=code&client_id=client_id&redirect_uri=http://yourhost/user/oauth/index&scope=basic&state=xxx">click here</a> </div>
AuthorizeAction() 代碼
/** * 展現受權頁面,用戶能夠點擊贊成進行受權 */ public function AuthorizeAction() { $request = Request::createFromGlobals(); $is_authorized = $request->request('is_authorized') ? true : false; //判斷用戶是否贊成受權 if ($is_authorized) { $response = new Response(); $server = $this->_server(); // validate the authorize request if (!$server->validateAuthorizeRequest($request, $response)) { $response->send(); die; } $server->handleAuthorizeRequest($request, $response, $is_authorized)->send(); return false; } //將請求受權中帶來的各個參數,寫入受權頁中的變量,用以受權表單POST提交。 $renderData = $_GET; $this->getView()->assign('data', $renderData)->render('oauth/authorize.php'); }
用戶受權頁面:oauth/authorize.php
<!DOCTYPE HTML> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>直達天庭 - 南天門</title> <link type="text/css" href="http://api.weibo.com/oauth2/css/oauthV3/oauth_web.css?version=20140625" rel="stylesheet"/> </head> <body class="WB_UIbody WB_widgets"> <div class="WB_xline1 oauth_xline" id="outer"> <div class="oauth_wrap"> <div class="oauth_header clearfix"> <h1 class="WB_logo" title="微博"><a href="http://yourhost">天庭</a></h1> <p class="login_account"> <span class="account_name">哪吒</span> <span class="vline">|</span><a href="http://yourhost/user/oauth/list" target="_blank">個人應用</a></span> </p> </div> <!-- 帶頭像 --> <div class="WB_panel oauth_main"> <form id="authZForm" name="authZForm" action="/user/oauth/authorize" method="post" node-type="form"> <div class="oauth_content"> <div class="oauth_main_content clearfix"> <div class="app_info clearfix"> <div class="app_info_main clearfix"> <div class="app_icon"> <img class="app_img" src="https://upload.api.weibo.com/square/aa397b7fgw1f556jk3z3bj20280283yc.jpg" alt="app"> </div> <div class="app_intro"> <h3><a href="http://app.weibo.com/t/feed/324Mrt" target="_blank">人間</a></h3> <div class="app_des">凡人</div> </div> </div> <div class="app_info_plus"> <div class="plus_tit"> http://app.weibo.com/t/feed/324Mrt<br/>有 1 個你關注的人鏈接 </div> <div class="app_user_list"> <ul class="clearfix"> </ul> </div> </div> </div> <div class="oauth_info clearfix"> <div class="oauth_list"> <div class="list_tit">將容許<a href="http://app.weibo.com/t/feed/324Mrt" target="_blank">人間</a>進行如下操做: </div> <ul class="do_list"> <li> <i class="icon_user"></i>得到你的我的信息,好友關係 </li> <li> <i class="icon_rss"></i>分享內容到你的微博 </li> <li> <i class="icon_comm"></i>得到你的評論 </li> </ul> </div> </div> </div> <!-- 登陸 --> <div class="oauth_login_box01 clearfix"> <input type="hidden" name="scope" id="scope" value="<?php echo $data['scope'];?>"/> <input type="hidden" name="response_type" value="<?php echo $data['response_type'];?>"/> <input type="hidden" name="redirect_uri" value="<?php echo $data['redirect_uri'];?>"/> <input type="hidden" name="client_id" value="<?php echo $data['client_id'];?>"/> <input type="hidden" name="state" value="<?php echo $data['state'];?>"/> <input type="hidden" name="is_authorized" value="1"/> <input type="hidden" name="grant_type" value="<?php echo $data['grant_type'];?>"/> <!-- </form> --> <div class="oauth_login_submit"> <p class="oauth_formbtn"><a node-type="submit" href="#" onclick="return false;" action-type="submit" class="WB_btn_link formbtn_01"></a><a node-type="cancel" href="javascript:;" action-type="cancel" class="WB_btn_cancel"></a></p> </div> </div> </div> </form> <!-- /登陸 --> </div> </div> </div> </body> </html> <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script> <script type="text/javascript"> $(document).ready(function(){ $(".WB_btn_link").click(function(){ $("#authZForm").submit(); }); }) </script>
TokenAction()
/** * 返回JSON結構數據 * { access_token: "977b1077556e9b23ff07ef7606a5eaf947f27d41", expires_in: 3600, token_type: "Bearer", scope: "basic", refresh_token: "d2367887bdd743121adfe5fda5083064439f1cb1" } */ public function TokenAction() { $server = $this->_server(); $server->handleTokenRequest(Request::createFromGlobals())->send(); return false; }
ResourceAction() 代碼
public function ResourceAction() { $server = $this->_server(); //獲取受權用戶Session中保存的access_token,用access_token能夠請求權限範圍內的全部接口 $_POST['access_token'] = Yaf_Session::getInstance()->get('access_token'); // Handle a request to a resource and authenticate the access token if (!$server->verifyResourceRequest(Request::createFromGlobals())) { $server->getResponse()->send(); die; } echo json_encode(array('success' => true, 'message' => 'You accessed my APIs!')); return false; }
請求用戶資源:/user/oauth/resource
{ success: true, message: "You accessed my APIs!" }
實現思路:
Client端
對應的模板裏放置一個連接,用以跳轉至服務端的受權認證頁面/user/oauth/authorize。受權成功後,服務端會將對應的code和state參數,附在回調的redirect_uri裏,即:/user/oauth/index?code=fcd6a9589e7ab43398e4e5349b23846babc79fab&state=xxx,在indexAction中解析出回調的code,用以請求接口/user/oauth/token,來交換access_token。
Server端
Server端
Server端
LAST:
Redis