CI环境下开发Oauth2.0开放平台


Oauth2.0


0x01.About

最近在搭建Oauth2.0第三方接入开放平台,主要是使用Github开源项目服务模块https://github.com/bshaffer/oauth2-server-php和CodeIgniter结合。

一般来说做开放平台主要包括:Oauth2.0认证平台、Resource资源API平台、Open开发者注册平台,以及API说明等。

Oauth2.0测试平台已经搭建好,请访问 http://oauth2.homeway.me/oauth/test/



0x02.About Oauth2.0

OAuth 2.0授权前,第三方应用必须到平台上进行注册,注册过程中可能需要填写的内容有:应用类型,授权成功回调地址,以及其他平台需要的资料(应用名称、网址、介绍、LOGO图片等)。

OAuth 2.0标准主要围绕三类应用:Web应用、基于客户端的应用、原生应用。

应用在Open开发者平台注册完成会得到一个应用client_id和一个client_secret,一般叫App Key,密钥叫App Secret,这两样东西作用跟用户名密码是一样的。

OAuth 2.0 RFC 中提到的授权方式有四种:授权码(Authorization Code)、隐式授权(Implicit Grant)、用户口令(Resource Owner Password Credentials)、应用口令(Client Credentials)。

这四种方式最终的目的都是要获得Access Token,然后通过请求Resource服务器获取资源。



0x03.Grant_type

说说每种授权方式使用到的地方,或授权的方式。

Authorization Code

Authorization Code

授权码方式在很多地方都有用到,微博登陆,微信登陆等都是。

认证过程主要是跳转到Oauth2.0平台,认证后跳转回第三方应用平台,并通过callback的url中携带code、state、token_type等信息,然后第三方平台通过code获取到access_token,进而调用开放API获取到资源。

第三方请求过程必须附带,response_type(回调类型:code,token),client_id(开发者app key),redirect_uri(回调链接),state(防止csrf,authorization认证跳转后原样返回)。

例如:http://localhost:8085/oauth2/authorize/index?redirect_uri=http://homeway.me&response_type=code&client_id=testclient&state=ae5f8c93dc51d856d6536aec528c31c6f6450458

测试例子:http://brentertainment.com/oauth2/

第一步:跳转到Oauth2.0服务器:

认证过程中会请求scope权限表,用户可以拒绝相应权限。

跳转到Oauth2.0服务器

第二步:用户确认请求的权限,回调得到code:

用户确认请求的权限

第三步:第三方平台通过code得到access_token,然后通过API调用Resource服务器资源。

这个过程需要发送client_idclient_secret(App Secret),grant_type(’authorization_code’),coderedirect_uri给oauth2服务器获取access_token

例如:http://brentertainment.com/oauth2/client/request_token/authorization_code?code=bab6b7dee32f629397acbb16a4d8e50c6c3d424d


Implicit Grant

隐式授权流程(Implicit Grant)其实就是Authorization Code的一个简化版本,不是回调code,而是直接回调access_token给第三方开发者,response_type变为token,其他和Authorization Code一样。

例如:http://brentertainment.com/oauth2/lockdin/authorize?response_type=token&client_id=demoapp&redirect_uri=http%3A%2F%2Fbrentertainment.com%2Foauth2%2Fclient%2Freceive_implicit_token&state=377edd18bd3070e4317889b0b3371c16

跳转后就得到了,如下链接:http://brentertainment.com/oauth2/client/receive_implicit_token#access_token=a845c2c81bc57613bbc5dee1fec173a3fbd0f474&expires_in=3600&token_type=Bearer&state=377edd18bd3070e4317889b0b3371c16


Client Credentials

应用授权(Client Credentials)主要用于第三方应用直接获取一些公开的数据,不需要用户跳转认证,也不需要获取用户的openid,因为都是一些公共的资源。

Client Credentials

我的请求数据为:{client_id: "testclient", client_secret: "testpass", grant_type: "client_credentials", scope: "userinfo cloud file node"}

Oauth2给我的回调数据:{"access_token":"417206d0e162d743338c04da9f8eb72f99daff6b","expires_in":3600,"token_type":"Bearer","scope":"userinfo cloud file node"}

可以看到有了access_token,然后我就可以用access_token去找Resource服务器要资源了,这里限定了scope权限表,表的权限在open平台注册的时候就确定下来了。


Resource Owner Password Credentials

用户口令(Resource Owner Password Credentials)适合内部应用调用使用,比如公司有两个平台,A和B,那么我就可以在Oauth2下通过Password Credentials模式实现A应用与B应用之间通信,还可以开放内部接口。

Client Credentials

请求的数据格式是:
{grant_type: "password username:"user", password: "pass",client_id: ""testclient", client_secret: "testpass", scope: "userinfo cloud file node}

回调数据比Client Credentials多了一个refresh_token:

{"access_token":"8a478275f8d2d5ac767f94ef0684a1fc2883eb24", "expires_in":3600, "token_type":"Bearer", "scope":"userinfo cloud file node", "refresh_token":"69a5e7b995ed4376bd6dd58380bfe09b51137dcb"}

那么当access_token过期后,就可以通过refresh_token再次激活一个新的access_token,黑魔法,自己给自己开后门。

激活请求发送的数据为:
{grant_type: "refresh_token", username:"user", password: "pass", client_id: ""testclient", client_secret: "testpass", scope: "userinfo cloud file node}

返回还是一个新的access_token数据。



0x04.CodeIgniter与Oauth2.0

四种授权方式都说过了,那么就开始搭建基于CodeIgniter的Oauth2.0平台了。

基础环境搭建

1.下载CI框架:$wget https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.0.0

2.解压 $unzip CodeIgniter-3.0.0.zip

3.进入library目录 $cd CodeIgniter-3.0.0/application/libraries

4.获取oauth2-php-server: git clone https://github.com/bshaffer/oauth2-server-php && mv -f oauth2-server-php oauth2

5.通过composer安装 oauth2-server-php :cd oauth2 && composer install

如果国内composer安装慢的话,我打了一个包,可以再这里下载到:oauth2-server-php.zip

Oauth2.0数据库

好了,ci和oauth2都处理好了,接下来导入下数据库的sql文件。

oauth2.0平台支持多种数据库,可以在oauth2/src/Oauth2/Storage/里面看到,有mongodb、mysql、redis等。

这里就选简单的mysql吧,数据库主要包含oauth_access_tokens、oauth_authorization_codes、oauth_clients、oauth_jwt、oauth_refresh_tokens、oauth_scopes、oauth_users几个表。

oauth_users是Password Credentials认证的时候用的表,oauth_scopes存放权限表,oauth_refresh_tokens是Password Credentials认证的时候的refresh_token表,oauth_clients存放开发者注册的信息表。

sql文件可以在这里下载:http://homeway.me/code/oauth2.sql

Server服务

接下来在CodeIgniter-3.0.0/application/libraries/oauth2里面新建一个server.php
用于对oauth2内调用与对外ci服务的接口。

###创建一个Authorization Code服务

class Server{
  function __construct(){
    OAuth2\Autoloader::register();
    $this->storage = new OAuth2\Storage\Pdo(array('dsn' => 'mysql:dbname=oauth;host=localhost', 'username' => '', 'password' => ''));
    $this->server = new OAuth2\Server($this->storage, array('allow_implicit' => true));
    $this->request = OAuth2\Request::createFromGlobals();
    $this->response = new OAuth2\Response();
  }
  public function authorize($is_authorized){
    $this->server->addGrantType(new OAuth2\GrantType\AuthorizationCode($this->storage));
    $this->server->handleAuthorizeRequest($this->request, $this->response, $is_authorized);
    if ($is_authorized) {
      $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
      header("Location: ".$response->getHttpHeader('Location'));
    }
    $response->send();
  }
}

###创建一个Password Credentials服务

class Server{
  function __construct(){
    OAuth2\Autoloader::register();
    $this->storage = new OAuth2\Storage\Pdo(array('dsn' => 'mysql:dbname=oauth;host=localhost', 'username' => '', 'password' => ''));
    $this->server = new OAuth2\Server($this->storage, array('allow_implicit' => true));
    $this->request = OAuth2\Request::createFromGlobals();
    $this->response = new OAuth2\Response();
  }
  public function password_credentials(){
    $users = array("user" => array("password" => 'pass', 'first_name' => 'homeway', 'last_name' => 'yao'));
    $storage = new OAuth2\Storage\Memory(array('user_credentials' => $users));//user是认证的账户,在表oauth_users中
    $this->server->addGrantType(new OAuth2\GrantType\UserCredentials($storage));
    $this->server->handleTokenRequest($this->request)->send();
  }
}

###创建一个Client Credentials服务

class Server{
  function __construct(){
    OAuth2\Autoloader::register();
    $this->storage = new OAuth2\Storage\Pdo(array('dsn' => 'mysql:dbname=oauth;host=localhost', 'username' => '', 'password' => ''));
    $this->server = new OAuth2\Server($this->storage, array('allow_implicit' => true));
    $this->request = OAuth2\Request::createFromGlobals();
    $this->response = new OAuth2\Response();
  }
  public function client_credentials(){
    $this->server->addGrantType(new OAuth2\GrantType\ClientCredentials($this->storage, array("allow_credentials_in_request_body" => true)));
    $this->server->handleTokenRequest($this->request)->send();
  }
}

###创建一个refresh_token服务

class Server{
  function __construct(){
    OAuth2\Autoloader::register();
    $this->storage = new OAuth2\Storage\Pdo(array('dsn' => 'mysql:dbname=oauth;host=localhost', 'username' => '', 'password' => ''));
    $this->server = new OAuth2\Server($this->storage, array('allow_implicit' => true));
    $this->request = OAuth2\Request::createFromGlobals();
    $this->response = new OAuth2\Response();
  }
  public function refresh_token(){
    $this->server->addGrantType(new OAuth2\GrantType\RefreshToken($this->storage, array(
         "always_issue_new_refresh_token" => true,
      "unset_refresh_token_after_use" => true,
      "refresh_token_lifetime" => 2419200,
    )));
    $this->server->handleTokenRequest($this->request)->send();
  }
}

0x04.About Package

篇幅太大了,我觉定,把代码打包下来,好了。^.().^

http://homeway.me/code/build-oauth2-under-codeigniter.zip

下面是打包好的测试平台你也可以通过http://oauth2.homeway.me/oauth/test/来进入测试平台。

平台web访问路径为:/oauth/test//oauth2/RefreshToken,/oauth2/resource,/oauth2/authorize/token,/oauth2/PasswordCredentials,/oauth2/ClientCredentials,你也可以从相应的源码中读到这些地址。

build-oauth2-under-codeigniter



参考:

1.http://tools.ietf.org/html/rfc6749
2.http://brentertainment.com/oauth2/
3.oauth2-server-php-docs
4.新浪oauth2授权机制说明
5.腾讯OAuth2.0简介
6.腾讯API调试平台




本文出自 夏日小草,转载请注明出处:http://homeway.me/2015/06/29/build-oauth2-under-codeigniter/

-by小草

2015-06-29 02:04:10

Fork me on GitHub