EvaOAuth0.1 文档
日志未经声明,均为 AlloVince 原创。本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
EvaOAuth1.0 已经发布,请去新版本页面查看内容,本页内容不再维护
EvaOAuth是一个统一接口设计,兼容 OAuth1.0 与 OAuth2.0 规范的 php oauth 登录模块,目前支持超过 20 个主流网站的 OAuth 登录,包括:
- 国外
- Facebook OAuth2
- Twitter OAuth1
- Google OAuth2
- Github OAuth2
- Msn Live OAuth2
- Flickr OAuth1
- LinkedIn OAuth1
- Yahoo OAuth1
- Dropbox OAuth1
- Foursquare OAuth2
- Disqus OAuth2
- 国内
- 豆瓣 Douban OAuth1
- 豆瓣 Douban OAuth2
- 微博 Weibo OAuth2
- 人人网 Renren OAuth2
- 腾讯 QQ Tencent OAuth2
- 开心网 Kaixin OAuth2
- 百度 Baidu OAuth2
- 360 Qihoo OAuth2
- 网易微博 Netease OAuth2
- 搜狐微博 Sohu OAuth1
- 天涯 Tianya OAuth1
EvaOAuth 统一接口规范,上面的任何一个第三方网站,在使用 EvaOAuth 时的代码与流程都是完全一致的,也可以很简单的扩展并加入新的第三方网站。
最终可以用 20 行左右代码实现以上所有支持网站的完整 OAuth 登录授权。
获得代码
推荐在项目中使用 Composer 进行一键安装。
请编辑 composer.json,加入
"require": {
"AlloVince/EvaOAuth": "dev-master"
},
然后运行
php composer.phar install
即可。
EvaOAuth 要求 PHP 版本必须高于 5.3.3,并主要依赖以下几个 ZF2 模块:
- ZendOAuth
- Zend\Session 储存 Token 信息,也可以自己扩展 Storage\StorageInterface 实现其他存储方式
- Zend\Json
在同目录下会自动创建 vendor 目录并下载所有的依赖,在你的项目中,只需要包含自动生成的 vendor/autoload.php 即可。
或者请访问EvaOAuth 的 Github 项目主页。
###在 Windows 环境下 composer.phar 的安装配置
参考之前的ZF2 在 Windows 下的环境搭建,假设我们的 php.exe 目录在 d:\xampp\php,那么首先将 php 目录加入 windows 环境变量。
cd d:\xampp\php
php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
同目录下编辑文件 composer.bat,内容为
@ECHO OFF
SET composerScript=composer.phar
php "%~dp0%composerScript%" %*
运行
composer -V
检查 composer 安装是否成功。
进入 EvaOAuth 目录下运行:
php D:\xampp\php\composer.phar install
申请应用
实现 OAuth 登录必须先在相应的第三方网站上申请应用并获得的 consumer key 与 consumer secret,每个网站可能叫法不太一样,以豆瓣为例:
访问豆瓣开发者,我的应用->创建新应用。创建完毕后
- 豆瓣应用的 API Key 对应 EvaOAuth 的 consumer key
- 豆瓣应用的 Secret 对应 EvaOAuth 的 consumer secret
快速开始
假设我们将 EvaOAuth 文件夹命名为 OAuth 并可以用http://localhost/OAuth/访问,同时已经安装好了所有的依赖。我们以豆瓣的 OAuth2.0 为例(因为豆瓣没有限制 CallbackUrl 的域,非常方便测试),用几十行代码构建一个完整的 OAuth 登录:
###获得 Request Token 并跳转到第三方进行授权
首先编写一个文件 request.php,内容如下:
require_once './vendor/autoload.php';
use EvaOAuth\Service as OAuthService;
$oauth = new OAuthService();
$oauth->setOptions(array(
'callbackUrl' => 'http://localhost/EvaOAuth/examples/access.php',
'consumerKey' => 'XXX',
'consumerSecret' => 'YYY',
));
$oauth->initAdapter('Douban', 'OAuth2');
$requestToken = $oauth->getAdapter()->getRequestToken();
$oauth->getStorage()->saveRequestToken($requestToken);
$requestTokenUrl = $oauth->getAdapter()->getRequestTokenUrl();
header("location: $requestTokenUrl");
将 consumerKey 和 consumerSecret 替换为在豆瓣申请应用的 API Key 与 Secret,然后访问
http://localhost/EvaOAuth/examples/request.php
不出意外的话会被引导向豆瓣进行授权。
这一步中,我们取得了一个 Request Token,然后将其暂存在 Session 里。然后被跳转往第三方网站进行授权。
虽然 Request Token 只存在于 OAuth1.0 规范,但是为了兼容两个规范,即便是 OAuth2.0 中,EvaOAuth 也会构建一个虚拟的 Request Token。
授权后会被带往我们指定的链接 callbackUrl。
###用 Request Token 换取 Access Token
继续编写另一个文件 access.php
require_once './vendor/autoload.php';
use EvaOAuth\Service as OAuthService;
$oauth = new OAuthService();
$oauth->setOptions(array(
'callbackUrl' => 'http://localhost/EvaOAuth/examples/access.php',
'consumerKey' => 'XXX',
'consumerSecret' => 'YYY',
));
$oauth->initAdapter('Douban', 'OAuth2');
$requestToken = $oauth->getStorage()->getRequestToken();
$accessToken = $oauth->getAdapter()->getAccessToken($_GET, $requestToken);
$accessTokenArray = $oauth->getAdapter()->accessTokenToArray($accessToken);
$oauth->getStorage()->saveAccessToken($accessTokenArray);
$oauth->getStorage()->clearRequestToken();
print_r($accessTokenArray);
在这一步中,从 Session 中取出上一步获得的 Request Token,配合 CallbackUrl 中携带的参数,最终会换取一个授权的 Access Token。上例中我们会看到最终获得的 Access Token 信息:
Array (
[adapterKey] => douban
[token] => tokenXXXXXXX
[expireTime] => 2012-12-06 15:20:38
[refreshToken] => refreshTokenXXXXXX
[version] => OAuth2
[remoteUserId] => 1291360
)
###使用 Access Token 访问 API
取得 Access Token 后,我们可以根据需求将其存入数据库或以其他方式存放。如果需要携带 Access Token 访问 API 也很简单,比如使用上例中的$accessTokenArray:
$oauth = new OAuthService();
$oauth->setOptions(array(
'consumerKey' => 'XXX',
'consumerSecret' => 'YYY',
));
$oauth->initByAccessToken($accessTokenArray);
$adapter = $oauth->getAdapter();
$client = $adapter->getHttpClient();
$client->setUri('https://api.douban.com/v2/user/~me');
$response = $client->send();
print_r($response->getBody());
Access Token 格式参考
EvaOAuth 最终返回的 Access Token 格式是统一的,但是由于第三方应用规定的差别,并不是所有的参数都一定存在:
- adapterKey (Required) : 第三方网站名,全小写
- token (Required) : Access Token
- tokenSecret : Access Token Secret,仅在 OAuth1.0 中存在
- version (Required) : 值为 OAuth1/OAuth2
- refreshToken : Refresh Token
- expireTime : Access Token 过期时间,为 UTC 时间
- remoteUserId (Required) : 当前用户在第三方网站的 User Id
- remoteUserName : 当前用户在第三方网站的 User Name
- remoteExtra : 取得 Access Token 时的其他附加信息,如果有则为一个 Json 字符串
OAuth 登录判断
每次用户的 OAuth 登录,只需要判定 adapterKey/version/remoteUserId 三个值完全一致时,即可认为是同一用户。
注意事项
很多第三方应用内需要将测试用的域名加入白名单。
Yahoo OAuth 必须在 App Permissions 栏选择并设定至少一项权限,否则会出现 oauth_problem=consumer_key_rejected 错误
由于 Zend Http 新版本存在 Bug,可能会引起
Fatal error: Call to a member function connect() on a non-object in Zend/Http/Client.php
这样的报错,目前修复的方法是强制使用旧版本的 Zend Http,项目 composer.json 中指定:
"allovince/evaoauth": "dev-master",
"zendframework/zend-http": "2.2.3",
重新运行 composer 即可
评论服务尚未配置。反馈或勘误