Building OAuth2.0 services based on the ThinkPHP framework has been engaged in OAuth2.0 stuff over the past few days, writing SDK stuff, in order to gain a deeper understanding of the server's OAuth Authentication mechanism, I built a php OAuth environment and transplanted it to my familiar tp framework. Let's talk a lot about it. Build OAuth2.0 service based on ThinkPHP framework
I have been working on OAuth2.0 and writing SDKs for the past few days. to gain a deeper understanding of the OAuth Authentication mechanism on the server, I have built a php OAuth environment, and transplanted it to the familiar tp framework.
Let's talk a lot about it.
?
In fact, the php version of OAuth2.0 is available on the Internet.
You can in http://code.google.com/p/oauth2-php? Find the source code and implement the data modes of PDO and MongoDB. Here I also integrate the code in TP.
?
Okay. here we can decompress the downloaded package, change the name of OAuth. inc under Lib to OAuth2.class. php, and put it in the directory of the tp core package:
?
/Extend/Library/ORG/OAuth/OAuth2.class.php
?
Next we will inherit this class;
Create a new ThinkOAuth2.class. php file in this directory:
?
Db = Db: getInstance (C ('Oss _ DB_DSN ')); $ this-> table = array ('auth _ codes '=> C ('Oss _ CODES_TABLE'), 'clients '=> C ('Oss _ CLIENTS_TABLE '), 'tokens' => C ('Oss _ TOKEN_TABLE ');}/*** destructor */function _ destruct () {$ this-> db = NULL; // Release db connection} private function handleException ($ e) {echo "Database error :". $ e-> getMessage (); exit;}/*** added client * @ param string $ client_id * @ param string $ c Lient_secret * @ param string $ redirect_uri */public function addClient ($ client_id, $ client_secret, $ redirect_uri) {$ time = time (); $ SQL = "INSERT INTO {$ this-> table ['clients ']}". "(client_id, client_secret, redirect_uri, create_time) VALUES (\" {$ client_id} \ ", \" {$ client_secret} \ ", \" {$ redirect_uri }\", \ "{$ time} \") "; $ this-> db-> execute ($ SQL);}/*** Implements oauth1: checkClientCredentials ()*@ See oau2::: checkClientCredentials () */protected function checkClientCredentials ($ client_id, $ client_secret = NULL) {$ SQL = "SELECT client_secret FROM {$ this-> table ['clients']}". "WHERE client_id = \" {$ client_id} \ ""; $ result = $ this-> db-> query ($ SQL); if ($ client_secret = NULL) {return $ result! = FALSE;} // Log: write ("checkClientCredentials :". $ result); // Log: write ("checkClientCredentials :". $ result [0]); // Log: write ("checkClientCredentials :". $ result [0] ["client_secret"]); return $ result [0] ["client_secret"] = $ client_secret;}/*** Implements oau22 :: getRedirectUri (). * @ see oauh2: getRedirectUri () */protected function getRedirectUri ($ client_id) {$ SQL = "SELECT redirect_uri FROM {$ this -> Table ['clients ']} ". "WHERE client_id = \" {$ client_id} \ ""; $ result = $ this-> db-> query ($ SQL); if ($ result = FALSE) {return FALSE;} // Log: write ("getRedirectUri :". $ result); // Log: write ("getRedirectUri :". $ result [0]); // Log: write ("getRedirectUri :". $ result [0] ["redirect_uri"]); return isset ($ result [0] ["redirect_uri"]) & $ result [0] ["redirect_uri"]? $ Result [0] ["redirect_uri"]: NULL;}/*** Implements oau2:: getAccessToken (). * @ see oau2:: getAccessToken () */protected function getAccessToken ($ access_token) {$ SQL = "SELECT client_id, expires, scope FROM {$ this-> table ['tokens']} ". "WHERE access_token = \" {$ access_token} \ ""; $ result = $ this-> db-> query ($ SQL); // Log: write ("getAccessToken: ". $ result); // Log: write ("getAccessToken :". $ result [0]); return $ result! = FALSE? $ Result: NULL;}/*** Implements oau2:: setAccessToken (). * @ see oau2:: setAccessToken () */protected function setAccessToken ($ access_token, $ client_id, $ expires, $ scope = NULL) {$ SQL = "INSERT INTO {$ this-> table ['tokens']}". "(access_token, client_id, expires, scope )". "VALUES (\" {$ access_token} \ ", \" {$ client_id} \ ", \" {$ expires} \ ", \" {$ scope }\") "; $ this-> db-> execute ($ SQL);}/*** Overrides O Auyy: getSupportedGrantTypes (). * @ see oau2:: getSupportedGrantTypes () */protected function getSupportedGrantTypes () {return array (OAUTH2_GRANT_TYPE_AUTH_CODE);}/*** Overrides oau2:: getAuthCode (). * @ see oau2:: getAuthCode () */protected function getAuthCode ($ code) {$ SQL = "SELECT code, client_id, redirect_uri, expires, scope ". "FROM {$ this-> table ['auth _ codes ']} WHERE code = \" {$ code} \ ""; $ r Esult = $ this-> db-> query ($ SQL); // Log: write ("getAuthcode :". $ result); // Log: write ("getAuthcode :". $ result [0]); // Log: write ("getAuthcode :". $ result [0] ["code"]); return $ result! = FALSE? $ Result [0]: NULL;}/*** Overrides oau2:: setAuthCode (). * @ see oau2:: setAuthCode () */protected function setAuthCode ($ code, $ client_id, $ redirect_uri, $ expires, $ scope = NULL) {$ time = time (); $ SQL = "INSERT INTO {$ this-> table ['auth _ Code']}". "(code, client_id, redirect_uri, expires, scope )". "VALUES (\" $ {code} \ ", \" $ {client_id} \ ", \" $ {redirect_uri} \ ", \" $ {expires }\", \ "$ {scope} \") "; $ result = $ this-> db-> execute ($ SQL);}/*** Overrides oauty2: checkUserCredentials (). * @ see oauth1: checkUserCredentials () */protected function checkUserCredentials ($ client_id, $ username, $ password) {return TRUE ;}}
?
? Here we need to create a database:
?
CREATE TABLE `oauth_client` ( `id` bigint(20) NOT NULL auto_increment, `client_id` varchar(32) NOT NULL, `client_secret` varchar(32) NOT NULL, `redirect_uri` varchar(200) NOT NULL, `create_time` int(20) default NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;CREATE TABLE `oauth_code` ( `id` bigint(20) NOT NULL auto_increment, `client_id` varchar(32) NOT NULL, `user_id` varchar(32) NOT NULL, `code` varchar(40) NOT NULL, `redirect_uri` varchar(200) NOT NULL, `expires` int(11) NOT NULL, `scope` varchar(250) default NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE `oauth_token` ( `id` bigint(20) NOT NULL auto_increment, `client_id` varchar(32) NOT NULL, `user_id` varchar(32) NOT NULL, `access_token` varchar(40) NOT NULL, `refresh_token` varchar(40) NOT NULL, `expires` int(11) NOT NULL, `scope` varchar(200) default NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
?
?
You can set the name of the above database table, but you need to configure the table name in config. php:
?
'OAUTH2_CODES_TABLE'=>'oauth_code','OAUTH2_CLIENTS_TABLE'=>'oauth_client','OAUTH2_TOKEN_TABLE'=>'oauth_token',
?
If the OAuth server is not the current server, you need to specify the DSN address:
?
?
'OAUTH2_DB_DSN'=>'mysql://root:mima@l:3306/database'
?
?
Well, the general core library code is like this. Use it Next
?
We create an OAuth Action to perform some oau2's verification (OauthAction. class. php)
?
Import ("ORG. OAuth. thinkoau2"); class OauthAction extends Action {private $ oauth = NULL; function _ initialize () {header ("Content-Type: application/json "); header ("Cache-Control: no-store"); $ this-> oauth = new thinkoau2();} public function index () {header ("Content-Type: application/json; charset = utf-8 "); $ this-> ajaxReturn (null, 'auth-server-start', 1, 'json');} public function access_token () {$ this-> oauth-> grantAccessToken ();} // permission verification public function authorize () {if ($ _ POST) {$ this-> oauth-> finishClientAuthorization ($ _ POST ["accept"] = "Yep", $ _ POST); return ;} /// form preparation $ auth_params = $ this-> oauth-> getAuthorizeParams (); $ this-> assign ("params", $ auth_params ); $ this-> display ();} public function addclient () {if ($ _ POST & isset ($ _ POST ["client_id"]) & isset ($ _ POST ["client_secret"]) & isset ($ _ POST ["redirect_uri"]) {$ this-> oauth-> addClient ($ _ POST ["client_id"], $ _ POST ["client_secret"], $ _ POST ["redirect_uri"]); return ;}$ this-> display ();}}
?
?
Here we have created a private oauth object and init it during initialization.
?
The above code is not verified in the password part. in the third mode, the checkUserCredentials method in the ThinkOAuth class needs to be rewritten.
?
Continue to write a restricted resource code. We didn't use AOP for interception here, so I am going to simulate interception using a base class.
?
?
import("ORG.OAuth.ThinkOAuth2");class BaseAction extends Action {protected $oauth = NULL;function _initialize(){$this -> oauth = new ThinkOAuth2(); } public function index(){ if(!$this -> oauth -> verifyAccessToken()){ $this -> ajaxReturn(null, 'no,no,no', 0, 'json'); exit(); }$this -> ajaxReturn(null, 'oauth-server', 1, 'json'); } }
?
? Next, we will use a UserAction to inherit it to achieve the restricted purpose, as shown below:
?
?
class UserAction extends BaseAction { public function index(){if(!$this -> oauth -> verifyAccessToken()){ $this -> ajaxReturn(null, 'no,no,no', 0, 'json'); }$this -> ajaxReturn(null, 'oauth-server', 1, 'json'); } }
?
?
?
?
Finally, why do we need to couple user_id into the OAuth table? Because we sometimes need to return the user_id from the access_token, the above table can solve this problem, but there is also a way to automatically include the user_id when the access_token is generated and then encrypt it, you can retrieve the user_id directly from the access_token during decoding. Here, the user_id and password verification are not implemented. you need to inherit the thinkoau22. or modify the checkUserCredentials method .?In addition, I think this set of things is better in the REST mode!