代码已push到github欢迎star: https://github.com/grasses/codeigniter-oauth2-serverphp
最近在搭建Oauth2.0第三方接入开放平台,主要是使用Github开源项目服务模块https://github.com/bshaffer/oauth2-server-php和CodeIgniter结合。node
通常来讲作开放平台主要包括:Oauth2.0认证平台、Resource资源API平台、Open开发者注册平台,以及API说明等。mysql
Oauth2.0测试平台已经搭建好,请访问 http://oauth2.homeway.me/oauth2/test/git
OAuth 2.0受权前,第三方应用必须到平台上进行注册,注册过程当中可能须要填写的内容有:应用类型,受权成功回调地址,以及其余平台须要的资料(应用名称、网址、介绍、LOGO图片等)。github
OAuth 2.0标准主要围绕三类应用:Web应用、基于客户端的应用、原生应用。web
应用在Open开发者平台注册完成会获得一个应用client_id和一个client_secret,通常叫App Key
,密钥叫App Secret
,这两样东西做用跟用户名密码是同样的。redis
OAuth 2.0 RFC 中提到的受权方式有四种:受权码(Authorization Code)、隐式受权(Implicit Grant)、用户口令(Resource Owner Password Credentials)、应用口令(Client Credentials)。sql
这四种方式最终的目的都是要得到Access Token,而后经过请求Resource服务器获取资源。mongodb
说说每种受权方式使用到的地方,或受权的方式。
受权码方式在不少地方都有用到,微博登录,微信登录等都是。
认证过程主要是跳转到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
权限表,用户能够拒绝相应权限。
第二步:用户确认请求的权限,回调获得code:
第三步:第三方平台经过code获得access_token,而后经过API调用Resource服务器资源。
这个过程须要发送client_id
,client_secret
(App Secret),grant_type
('authorization_code'),code
,redirect_uri
给oauth2服务器获取access_token
。
例如:http://brentertainment.com/oauth2/client/request_token/authorization_code?code=bab6b7dee32f629397acbb16a4d8e50c6c3d424d
隐式受权流程(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)主要用于第三方应用直接获取一些公开的数据,不须要用户跳转认证,也不须要获取用户的openid,由于都是一些公共的资源。
个人请求数据为:{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)适合内部应用调用使用,好比公司有两个平台,A和B,那么我就能够在Oauth2下经过Password Credentials
模式实现A应用与B应用之间通讯,还能够开放内部接口。
请求的数据格式是:
`{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数据。
四种受权方式都说过了,那么就开始搭建基于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
好了,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
接下来在CodeIgniter-3.0.0/application/libraries/oauth2
里面新建一个server.php
,
用于对oauth2内调用与对外ci服务的接口。
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(); } }
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(); } }
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(); } }
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(); } }
篇幅太大了,我觉定,把代码打包下来,好了。^.().^
http://785igi.com1.z0.glb.clouddn.com/share/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
,你也能够从相应的源码中读到这些地址。
参考:
1.http://tools.ietf.org/html/rfc6749
2.http://brentertainment.com/oauth2/
3.oauth2-server-php-docs
4.新浪oauth2受权机制说明
5.腾讯OAuth2.0简介
6.腾讯API调试平台
-by小草
2015-06-29 02:04:10