【PHP】基于ThinkPHP框架搭建OAuth2.0服务

from:http://leyteris.iteye.com/blog/1483403

       这几天一直在搞OAuth2.0的东西,写SDK啥的,为了更加深入的了解服务端的OAuth验证机制,就自己动手搭了个php下OAuth的环境,并且将它移植到了自己比较熟的tp框架里。

废话不少说,开动。

 

其实网上是有OAuth2.0的php版本的。

你可以在http://code.google.com/p/oauth2-php/ 找到源代码,上面实现了PDO和MongoDB的数据模式。这里我也是基于这些代码在TP中进行整合的。

 

好,这里我们可以把下载下来的包解压,把Lib下的OAuth.inc改名为OAuth2.class.php后放到tp核心包下的目录下:

 

Tree代码  

  1. /Extend/Library/ORG/OAuth/OAuth2.class.php  

 

接下来我们要继承这个类;

在这个目录下新建一个ThinkOAuth2.class.php文件:

 

Php代码  

  1. <?php  
  2. /** 
  3.  * @category ORG 
  4.  * @package ORG 
  5.  * @author Leyteris 
  6.  * @version 2012.3.16 
  7.  */  
  8.   
  9. // OAUTH2_DB_DSN  数据库连接DSN  
  10. // OAUTH2_CODES_TABLE 服务器表名称  
  11. // OAUTH2_CLIENTS_TABLE 客户端表名称  
  12. // OAUTH2_TOKEN_TABLE 验证码表名称  
  13.   
  14. import("ORG.OAuth.OAuth2");  
  15.   
  16. class ThinkOAuth2 extends OAuth2 {  
  17.   
  18.     private $db;  
  19.     private $table;  
  20.   
  21.     /** 
  22.      * 构造 
  23.      */  
  24.     public function __construct() {  
  25.         parent::__construct();  
  26.         $this -> db = Db::getInstance(C('OAUTH2_DB_DSN'));  
  27.         $this -> table = array(  
  28.             'auth_codes'=>C('OAUTH2_CODES_TABLE'),  
  29.             'clients'=>C('OAUTH2_CLIENTS_TABLE'),  
  30.             'tokens'=>C('OAUTH2_TOKEN_TABLE')  
  31.         );  
  32.     }  
  33.   
  34.     /** 
  35.      * 析构 
  36.      */  
  37.     function __destruct() {  
  38.         $this->db = NULL; // Release db connection  
  39.     }  
  40.   
  41.     private function handleException($e) {  
  42.         echo "Database error: " . $e->getMessage();  
  43.         exit;  
  44.     }  
  45.   
  46.     /** 
  47.      *  
  48.      * 增加client 
  49.      * @param string $client_id 
  50.      * @param string $client_secret 
  51.      * @param string $redirect_uri 
  52.      */  
  53.     public function addClient($client_id, $client_secret, $redirect_uri) {  
  54.           
  55.         $time = time();  
  56.         $sql = "INSERT INTO {$this -> table['clients']} ".  
  57.             "(client_id, client_secret, redirect_uri, create_time) VALUES (\"{$client_id}\", \"{$client_secret}\", \"{$redirect_uri}\",\"{$time}\")";  
  58.           
  59.         $this -> db -> execute($sql);  
  60.           
  61.     }  
  62.   
  63.     /** 
  64.      * Implements OAuth2::checkClientCredentials() 
  65.      * @see OAuth2::checkClientCredentials() 
  66.      */  
  67.     protected function checkClientCredentials($client_id, $client_secret = NULL) {  
  68.           
  69.         $sql = "SELECT client_secret FROM {$this -> table['clients']} ".  
  70.             "WHERE client_id = \"{$client_id}\"";  
  71.           
  72.         $result = $this -> db -> query($sql);  
  73.         if ($client_secret === NULL) {  
  74.             return $result !== FALSE;  
  75.         }  
  76.           
  77.         //Log::write("checkClientCredentials : ".$result);  
  78.         //Log::write("checkClientCredentials : ".$result[0]);  
  79.         //Log::write("checkClientCredentials : ".$result[0]["client_secret"]);  
  80.           
  81.         return $result[0]["client_secret"] == $client_secret;  
  82.           
  83.     }  
  84.   
  85.     /** 
  86.      * Implements OAuth2::getRedirectUri(). 
  87.      * @see OAuth2::getRedirectUri() 
  88.      */  
  89.     protected function getRedirectUri($client_id) {  
  90.           
  91.         $sql = "SELECT redirect_uri FROM {$this -> table['clients']} ".  
  92.             "WHERE client_id = \"{$client_id}\"";  
  93.           
  94.         $result = $this -> db -> query($sql);  
  95.           
  96.         if ($result === FALSE) {  
  97.             return FALSE;  
  98.         }  
  99.           
  100.         //Log::write("getRedirectUri : ".$result);  
  101.         //Log::write("getRedirectUri : ".$result[0]);  
  102.         //Log::write("getRedirectUri : ".$result[0]["redirect_uri"]);  
  103.           
  104.         return isset($result[0]["redirect_uri"]) && $result[0]["redirect_uri"] ? $result[0]["redirect_uri"] : NULL;  
  105.           
  106.     }  
  107.   
  108.     /** 
  109.      * Implements OAuth2::getAccessToken(). 
  110.      * @see OAuth2::getAccessToken() 
  111.      */  
  112.     protected function getAccessToken($access_token) {  
  113.           
  114.         $sql = "SELECT client_id, expires, scope FROM {$this -> table['tokens']} ".  
  115.             "WHERE access_token = \"{$access_token}\"";  
  116.           
  117.         $result = $this -> db -> query($sql);  
  118.           
  119.         //Log::write("getAccessToken : ".$result);  
  120.         //Log::write("getAccessToken : ".$result[0]);  
  121.           
  122.         return $result !== FALSE ? $result : NULL;  
  123.           
  124.     }  
  125.   
  126.     /** 
  127.      * Implements OAuth2::setAccessToken(). 
  128.      * @see OAuth2::setAccessToken() 
  129.      */  
  130.     protected function setAccessToken($access_token, $client_id, $expires, $scope = NULL) {  
  131.           
  132.         $sql = "INSERT INTO {$this -> table['tokens']} ".  
  133.             "(access_token, client_id, expires, scope) ".  
  134.             "VALUES (\"{$access_token}\", \"{$client_id}\", \"{$expires}\", \"{$scope}\")";  
  135.           
  136.         $this -> db -> execute($sql);  
  137.           
  138.     }  
  139.   
  140.     /** 
  141.      * Overrides OAuth2::getSupportedGrantTypes(). 
  142.      * @see OAuth2::getSupportedGrantTypes() 
  143.      */  
  144.     protected function getSupportedGrantTypes() {  
  145.         return array(  
  146.             OAUTH2_GRANT_TYPE_AUTH_CODE  
  147.         );  
  148.     }  
  149.   
  150.     /** 
  151.      * Overrides OAuth2::getAuthCode(). 
  152.      * @see OAuth2::getAuthCode() 
  153.      */  
  154.     protected function getAuthCode($code) {  
  155.           
  156.         $sql = "SELECT code, client_id, redirect_uri, expires, scope ".  
  157.             "FROM {$this -> table['auth_codes']} WHERE code = \"{$code}\"";  
  158.           
  159.         $result = $this -> db -> query($sql);  
  160.           
  161.         //Log::write("getAuthcode : ".$result);  
  162.         //Log::write("getAuthcode : ".$result[0]);  
  163.         //Log::write("getAuthcode : ".$result[0]["code"]);  
  164.           
  165.         return $result !== FALSE ? $result[0] : NULL;  
  166.   
  167.     }  
  168.   
  169.     /** 
  170.      * Overrides OAuth2::setAuthCode(). 
  171.      * @see OAuth2::setAuthCode() 
  172.      */  
  173.     protected function setAuthCode($code, $client_id, $redirect_uri, $expires, $scope = NULL) {  
  174.           
  175.         $time = time();  
  176.         $sql = "INSERT INTO {$this -> table['auth_codes']} ".  
  177.             "(code, client_id, redirect_uri, expires, scope) ".  
  178.             "VALUES (\"${code}\", \"${client_id}\", \"${redirect_uri}\", \"${expires}\", \"${scope}\")";  
  179.           
  180.         $result = $this -> db -> execute($sql);  
  181.   }  
  182.     
  183.   /** 
  184.    * Overrides OAuth2::checkUserCredentials(). 
  185.    * @see OAuth2::checkUserCredentials() 
  186.    */  
  187.   protected function checkUserCredentials($client_id, $username, $password){  
  188.     return TRUE;  
  189.   }  
  190. }  

 

 在这里我们需要创建数据库:

 

Sql代码  

  1. CREATE TABLE `oauth_client` (  
  2.   `id` bigint(20) NOT NULL auto_increment,  
  3.   `client_id` varchar(32) NOT NULL,  
  4.   `client_secret` varchar(32) NOT NULL,  
  5.   `redirect_uri` varchar(200) NOT NULL,  
  6.   `create_time` int(20) default NULL,  
  7.   PRIMARY KEY  (`id`)  
  8. ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;  
  9.   
  10. CREATE TABLE `oauth_code` (  
  11.   `id` bigint(20) NOT NULL auto_increment,  
  12.   `client_id` varchar(32) NOT NULL,  
  13.   `user_id` varchar(32) NOT NULL,  
  14.   `code` varchar(40) NOT NULL,  
  15.   `redirect_uri` varchar(200) NOT NULL,  
  16.   `expires` int(11) NOT NULL,  
  17.   `scope` varchar(250) default NULL,  
  18.   PRIMARY KEY  (`id`)  
  19. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;  
  20.   
  21. CREATE TABLE `oauth_token` (  
  22.   `id` bigint(20) NOT NULL auto_increment,  
  23.   `client_id` varchar(32) NOT NULL,  
  24.   `user_id` varchar(32) NOT NULL,  
  25.   `access_token` varchar(40) NOT NULL,  
  26.   `refresh_token` varchar(40) NOT NULL,  
  27.   `expires` int(11) NOT NULL,  
  28.   `scope` varchar(200) default NULL,  
  29.   PRIMARY KEY  (`id`)  
  30. ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;  

 

 

上面的数据库表名可以自己随便定;但是要在config.php配置表名:

 

Php代码  

  1. 'OAUTH2_CODES_TABLE'=>'oauth_code',  
  2. 'OAUTH2_CLIENTS_TABLE'=>'oauth_client',  
  3. 'OAUTH2_TOKEN_TABLE'=>'oauth_token',  

 

如果OAuth的服务器不是当前服务器,那就要指定下DSN地址了:

 

 

Php代码  

  1. 'OAUTH2_DB_DSN'=>'mysql://root:mima@l:3306/database'  

 

 

好了,大致的核心库代码就是如此。接下来要使用它

 

我们创建一个OAuth的Action负责OAuth2的一些验证(OauthAction.class.php)

 

Php代码  

  1. import("ORG.OAuth.ThinkOAuth2");  
  2.   
  3. class OauthAction extends Action {  
  4.       
  5.     private $oauth = NULL;  
  6.   
  7.     function _initialize(){  
  8.           
  9.         header("Content-Type: application/json");  
  10.         <span style="white-space: pre;">    </span>header("Cache-Control: no-store");  
  11.         $this -> oauth = new ThinkOAuth2();  
  12.   
  13.     }  
  14.       
  15.     public function index(){  
  16.           
  17.         header("Content-Type:application/json; charset=utf-8");  
  18.         $this -> ajaxReturn(null, 'oauth-server-start', 1, 'json');  
  19.           
  20.     }  
  21.       
  22.     public function access_token() {  
  23.           
  24.         $this -> oauth -> grantAccessToken();  
  25.   
  26.     }  
  27.       
  28.     //权限验证  
  29.     public function authorize() {  
  30.           
  31.         if ($_POST) {  
  32.             $this -> oauth -> finishClientAuthorization($_POST["accept"] == "Yep", $_POST);  
  33.             return;  
  34.         }  
  35.           
  36.         ///表单准备  
  37.         $auth_params = $this -> oauth -> getAuthorizeParams();  
  38.         $this -> assign("params", $auth_params);  
  39.         $this->display();  
  40.   
  41.     }  
  42.       
  43.     public function addclient() {  
  44.           
  45.         if ($_POST && isset($_POST["client_id"]) &&  
  46.          isset($_POST["client_secret"]) &&   
  47.             isset($_POST["redirect_uri"])) {  
  48.                   
  49.             $this -> oauth -> addClient($_POST["client_id"], $_POST["client_secret"], $_POST["redirect_uri"]);  
  50.             return;  
  51.         }  
  52.           
  53.         $this->display();  
  54.     }  
  55. }  

 

 

这里我们创建了一个私有的oauth对象并在初始化的时候去init它。

 

以上的代码在password那个部分没有做验证,第三种模式需要把ThinkOAuth类中的checkUserCredentials方法进行重写。

 

继续我们写一个受限资源代码。我们这里没有用AOP进行拦截,所以我准备直接用一个基类来模拟拦截。

 

 

Php代码  

  1. import("ORG.OAuth.ThinkOAuth2");  
  2.   
  3. class BaseAction extends Action {  
  4.       
  5.     protected $oauth = NULL;  
  6.   
  7.     function _initialize(){  
  8.           
  9.         $this -> oauth = new ThinkOAuth2();  
  10.   
  11.     }  
  12.       
  13.     public function index(){  
  14.           
  15.         if(!$this -> oauth -> verifyAccessToken()){  
  16.             $this -> ajaxReturn(null, 'no,no,no', 0, 'json');  
  17.             exit();  
  18.         }  
  19.         $this -> ajaxReturn(null, 'oauth-server', 1, 'json');  
  20.           
  21.     }  
  22.       
  23. }  

 

 接下来直接用一个UserAction来继承它达到受限的目的,如下:

 

 

Php代码  

  1. class UserAction extends BaseAction {  
  2.       
  3.     public function index(){  
  4.   
  5.         if(!$this -> oauth -> verifyAccessToken()){  
  6.             $this -> ajaxReturn(null, 'no,no,no', 0, 'json');  
  7.         }  
  8.         $this -> ajaxReturn(null, 'oauth-server', 1, 'json');  
  9.           
  10.     }  
  11.       
  12. }  

 

 

 

 

最后说明一点,为什么要把user_id耦合进OAuth的表呢?因为我们有时候需要从access_token返查user_id,上面的表就能解决这个问题,但其实还有一种方式是在对于access_token生成的时候自动包含user_id再进行加密,在解码的时候从access_token直接取出user_id就可以了。这里关于user_id和密码验证的都没有去实现,需要后期继承ThinkOAuth2类或者修改checkUserCredentials方法才能实现的。 另外这套东西用在REST模式下我认为更好!

时间: 2024-08-04 13:50:18

【PHP】基于ThinkPHP框架搭建OAuth2.0服务的相关文章

搭建oauth2.0服务端

问题描述 各位大侠:请教一个问题,第一次研究oauth2.0,想自己搭建一套oauth2.0服务器,从官网下载了DotNetOpenAuth.OAuth2的源代码,还是感觉无从下手,不知道哪位大侠有这方面的经验,请指教!..最好给出ASP.NET的搭建步骤,万分感谢! 解决方案 解决方案二:你研究咋样了,我也开始研究了,无从下手,想来个demo看看都下载不到解决方案三:同感,有思路拉吗?解决方案四:在tomcat下面能搭建Oauth2.0服务器?

基于thinkPHP框架实现留言板的方法

本文实例讲述了基于thinkPHP框架实现留言板的方法.分享给大家供大家参考,具体如下: 奋斗了一天,终于THINKPHP小邓留言版的概念版出来了 其实真的THINKPHP开发速度很快,作为一个互联网上"搬砖"的,从事这种 纯码农的事也是无可厚非的. 代码就实现了如下功能 1.留言功能. 2.验证功能. 3.分页显示功能. 就是写了几行代码(PS:页面设计代码不算,就算控制器和模型的代码) 下面我公布一下控制的器的代码,关于THINKPHP的代码规则我就不阐述了,看thinkphp手册

ThinkPHP框架搭建及常见问题(XAMPP安装失败、Apache/MySQL启动失败)_php实例

本文为大家详细分享了搭建ThinkPHP框架时遇到的问题,为大家提供了解决方法,具体内容如下 第一部分:框架搭建 我也是刚接触ThinkPHP,所以将目前的心得以及学习步骤按照我认为更容易理解的方式记录下来. 要使用ThinkPHP首先是要把环境搭建好,下面两个大体步骤来介绍: 第一步:下载软件 1.Xmapp(此软件将Apache.MySQL等集成了,使用起来很方便) 2.ThinkPHP3.2.3下载 第二步:搭建框架 1.将xmapp安装好,我们可以看到一个htdocs文件夹,我们可以将下

云服务器 ECS 建站教程:快速搭建 ThinkPHP 框架

快速搭建 ThinkPHP 框架 ThinkPHP 是一款免费开源的,快速.简单的面向对象的轻量级 PHP 开发框架,遵循 Apache2 开源协议发布,是为了敏捷 Web 应用开发和简化企业应用开发而诞生的. 适用对象 本文档介绍如何使用云市场的 ThinkPHP 框架(含智慧云虚机面板) 快速搭建 ThinkPHP 框架.适用于正在学习 PHP 或者已经基于 ThinkPHP 框架研发的开发者. 基本流程 购买 ThinkPHP 框架镜像. 上传您的程序. 切换 PHP 脚本适应您的程序.

快速搭建ThinkPHP框架教程

本文教你如何快速搭建ThinkPHP框架.ThinkPHP 是一款免费开源的,快速.简单的面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷 Web 应用开发和简化企业应用开发而诞生的.ThinkPHP 是国内最领先和最具影响力的 Web 应用开发框架,是开发者学习 PHP 及研发网站的不错选择. ##适用对象 本文档介绍如何使用云市场的 **ThinkPHP 框架(含智慧云虚机面板)** 快速搭建 ThinkPHP 框架.适用于正在学习 PHP 或者已经基于 Think

ThinkPHP框架中添加404错误页面以及访问安全

所有的网站项目都需要添加一个404页面,不仅友好,而且对网站优化也有一定的好处,而用ThinkPHP框架搭建的网站添加404页面的方法还是很简单的,利用的就是空类,空方法 第一步: 在Lib/Action文件夹下创建EmptyAction.class.PHP <?php class EmptyAction extends Action { function _empty(){ header("HTTP/1.0 404 Not Found"); $this->display(

利用OpenStreetMap(OSM)数据搭建一个地图服务

图 利用OSM数据简单发布的北京地图服务   一.OSM是什么        开放街道图(OpenStreetMap,简称OSM)是一个网上地图协作计划,目标是创造一个内容自由且能让所有人编辑的世界地图(wiki:http://wiki.openstreetmap.org/wiki/Main_Page).尤其值得称道的是,osm数据开源,可以自由下载使用. 二.OSM数据结构        OpenStreetMap包括空间数据以及属性数据.其中空间数据主要包括三种:点(Nodes).路(Way

thinkPHP框架对接支付宝即时到账接口回调操作示例_php实例

本文实例讲述了thinkPHP框架对接支付宝即时到账接口回调操作.分享给大家供大家参考,具体如下: 关于支付宝即时收款接口的对接过程,很简单,也有很多人发过,我这里就不在啰嗦了,对接完成后,在线支付成功后的回调,相对来说,是个难点,,我重点分享下我的经验. 我在开发二代旅游CMS(http://www.erdaicms.com)的时候,在回调的时候,也花了不少时间. 不管是支付宝接口好是微信支付接口,回调都分为跳转回调和异步通知回调,跳转回调是不保险的,加入客人支付完成后马上把支付页面关闭,没跳

老生常谈php中传统验证与thinkphp框架(必看篇)

PHP(超文本预处理器)可用于小型网站的搭建,当用户需要注册登录是,需要与后台数据库进行匹配合格才能注册和登录,传统的方式步骤繁多,需要先连接数据库再用sql语句进行插入. <?php header("Content-type: text/html; charset=utf-8"); $conn =mysqli_connect("localhost","root",""); if (!$conn){ echo "