http://www.rollosay.com/it/%E4%BD%BF%E7%94%A8OAuth-Server-PHP%E5%AE%9E%E7%8E%B0OAuth2%E6%9C%8D%E5%8A%A1

在现在的网络服务中,OAuth2.0服务已经很普遍了,无论是facebook或者微博的第三方登录,还是手机APP登录,都有很广泛的应用。
它主要的目的如下:
如果用户的照片在A网站,他想要在B网站使用A网站的头像,并不需要向B网站提供自己在A网站的用户名和密码,而直接给B一个Access Token来获取A站的照片
具体流程如下:
1)用户访问网站B
2)B需要验证用户的身份
3)B将用户定向到A网站,用户输入帐号密码登录A网站
4)A网站询问是否要将Authentication的权利给B网站
5)用户告诉A站可以将认证权给B站
6)A网站把Authorization Code发给B站
7)B站用Autorization Code向A站换取Access Token
8)当B站拥有Access Token时,就拥有了用户在A站的一些访问权限
这是典型的Authorization Code Grant,常常运用于网络应用之中

还有Implicit Grant认证方式,这个则省去了Auth Code,开放平台直接返回access_token和有效期,用户ID等数据
这种经常运用于手机客户端或者浏览器插件等没有在线服务器的应用

最后一种是Resource Owner Password Credentials Grant
这种是直接在应用中输入帐号密码,然后由应用XAuth技术将其提交给开放平台并得到Access Token
它经常用于PC可执行程序和手机应用,但由于存在一些争议,开发难度也较大,这里我就先不讨论他

安装

你可以在github上下载OAuth Server PHP,也可以用下列命令下载,不过内容都是一样的

Shell
1
2
3
mkdir my-oauth2-walkthrough
cd my-oauth2-walkthrough
git clone https://github.com/bshaffer/oauth2-server-php.git -b master

在这之后配置数据库

SQL
1
2
3
4
5
6
7
CREATE TABLE oauth_clients (client_id VARCHAR(80) NOT NULL, client_secret VARCHAR(80) NOT NULL, redirect_uri VARCHAR(2000) NOT NULL, grant_types VARCHAR(80), scope VARCHAR(100), user_id VARCHAR(80), CONSTRAINT clients_client_id_pk PRIMARY KEY (client_id));
CREATE TABLE oauth_access_tokens (access_token VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT access_token_pk PRIMARY KEY (access_token));
CREATE TABLE oauth_authorization_codes (authorization_code VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), redirect_uri VARCHAR(2000), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT auth_code_pk PRIMARY KEY (authorization_code));
CREATE TABLE oauth_refresh_tokens (refresh_token VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT refresh_token_pk PRIMARY KEY (refresh_token));
CREATE TABLE oauth_users (username VARCHAR(255) NOT NULL, password VARCHAR(2000), first_name VARCHAR(255), last_name VARCHAR(255), CONSTRAINT username_pk PRIMARY KEY (username));
CREATE TABLE oauth_scopes (scope TEXT, is_default BOOLEAN);
CREATE TABLE oauth_jwt (client_id VARCHAR(80) NOT NULL, subject VARCHAR(80), public_key VARCHAR(2000), CONSTRAINT jwt_client_id_pk PRIMARY KEY (client_id));

配置

我们来建立一个server.php文件来配置server,这个文件可以被所有的终端来调用。看require once就知道这个文件是平级的。

server.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$dsn      = 'mysql:dbname=my_oauth2_db;host=localhost';
$username = 'root';
$password = '';
 
// error reporting (this is a demo, after all!)
ini_set('display_errors',1);error_reporting(E_ALL);
 
// Autoloading (composer is preferred, but for this example let's just do this)
require_once('oauth2-server-php/src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register();
 
// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
$storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));
 
// Pass a storage object or array of storage objects to the OAuth2 server class
$server = new OAuth2\Server($storage);
 
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
$server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage));
 
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));

最后记得配置数据库PDO的用户名和密码

Token控制器

下面,我们将建立一个Token控制器,这个控制器URI将会返回OAuth2的Token给客户端

token.php
1
2
3
4
5
// include our OAuth2 Server object
require_once __DIR__.'/server.php';
 
// Handle a request for an OAuth2.0 Access Token and send the response to the client
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();

测试Token控制器

需要先创建一条记录,来注册一个新的应用

SQL
1
INSERT INTO oauth_clients (client_id, client_secret, redirect_uri) VALUES ("testclient", "testpass", "http://fake/");

然后用命令行调用

Shell
1
curl -u testclient:testpass http://localhost/token.php -d 'grant_type=client_credentials'

这里的URL只是示例,实地操作要确定能找到这个token.php
如果运行正常,则显示

JSON
1
{"access_token":"03807cb390319329bdf6c777d4dfae9c0d3b3c35","expires_in":3600,"token_type":"bearer","scope":null}

资源控制器的建立和测试

你创建了Token,你需要在API中测试它,于是你写了如下代码

resource.php
1
2
3
4
5
6
7
8
9
// include our OAuth2 Server object
require_once __DIR__.'/server.php';
 
// Handle a request for an OAuth2.0 Access Token and send the response to the client
if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) {
    $server->getResponse()->send();
    die;
}
echo json_encode(array('success' => true, 'message' => 'You accessed my APIs!'));

然后运行下面的命令,记得将YOUR_TOKEN替换成刚才得到的token,还有确保URL的正确

Shell
1
curl http://localhost/resource.php -d 'access_token=YOUR_TOKEN'

如果没出问题,则会得到下面的结果

JSON
1
{"success":true,"message":"You accessed my APIs!"}

认证控制器的创建和测试

验证控制器是OAuth2的杀手锏,它允许你的平台帮助用户验证第三方应用
它不像第一个例子中直接返回一个Access Token,这里稍微复杂一点

authorize.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// include our OAuth2 Server object
require_once __DIR__.'/server.php';
 
$request = OAuth2\Request::createFromGlobals();
$response = new OAuth2\Response();
 
// validate the authorize request
if (!$server->validateAuthorizeRequest($request, $response)) {
    $response->send();
    die;
}
// display an authorization form
if (empty($_POST)) {
  exit('
<form method="post">
  <label>Do You Authorize TestClient?</label><br />
  <input type="submit" name="authorized" value="yes">
  <input type="submit" name="authorized" value="no">
</form>');
}
 
// print the authorization code if the user has authorized your client
$is_authorized = ($_POST['authorized'] === 'yes');
$server->handleAuthorizeRequest($request, $response, $is_authorized);
if ($is_authorized) {
  // this is only here so that you get to see your code in the cURL request. Otherwise, we'd redirect back to the client
  $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
  exit("SUCCESS! Authorization Code: $code");
}
$response->send();

然后在浏览器中打开这个URL

URL
1
http://localhost/authorize.php?response_type=code&client_id=testclient&state=xyz

你将会看到一个表单,当你选择yes的时候会弹出你所获得的Authorization Code
现在你可以用这个Authorization Code来刚才建立的token.php获得TOKEN,命令如下

Shell
1
curl -u testclient:testpass http://localhost/token.php -d 'grant_type=authorization_code&code=YOUR_CODE'
 

就像刚才一样,你获得了一个TOKEN

Json
1
{"access_token":"6f05ad622a3d32a5a81aee5d73a5826adb8cbf63","expires_in":3600,"token_type":"bearer","scope":null}

请在30秒内完成这个操作,因为Authorization Code的有效期只有30秒

用Access Token联系本地用户

当你认证了一个用户并且分派了一个Token之后,你可能想知道彼时到底是哪个用户使用了这个Token
你可以使用handleAuthorizeRequest的可选参数user_id来完成,修改你的authorize.php文件

authorize.php
1
2
$userid = 1234; // A value on your server that identifies the user
$server->handleAuthorizeRequest($request, $response, $is_authorized, $userid);

这样一来,用户ID就伴随Token一起存进数据库了
当Token被客户端使用的时候,你就知道是哪个用户了,修改resource.php来完成任务

resource.php
1
2
3
4
5
6
7
if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) {
    $server->getResponse()->send();
    die;
}
 
$token = $server->getAccessTokenData(OAuth2\Request::createFromGlobals());
echo "User ID associated with this token is {$token['user_id']}";

通过阅读这篇文章体会:

  一、其实像新浪微博,QQ都是用了第二种方法Authorization Code,跳到授权页面,用户登录然后,

执行$server->handleAuthorizeRequest($request, $response, $is_authorized, $userid);把用户ID和token绑定起来,其实我有个疑问,为什么现在不直接把token返回给B站了,还要先返回code,然后再用code去请求token了,
     二、有的app应用直接用了本文第一种方法,

curl -u testclient:testpass http://localhost/token.php -d 'grant_type=client_credentials',这种的作用其实就是直接验证一下客户端是不是授权的客户端,其实感觉意义不大,如果源代码被人看了-u testclient:testpass直接就知道了,但是好处就是根据token令牌绑定用户ID,下次请求接口直接带参数token,就可以判断用户,并传回相应的信息。
       以上体会纯属个人看法,如有误解,请大家指出
 

oauth2(转载http://www.rollosay.com/it/%E4%BD%BF%E7%94%A8OAuth-Server-PHP%E5%AE%9E%E7%8E%B0OAuth2%E6%9C%8D%E5%8A%A1)的更多相关文章

  1. http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/

    http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%9 ...

  2. https://geewu.gitbooks.io/rabbitmq-quick/content/RabbitMQ%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C.html

    https://geewu.gitbooks.io/rabbitmq-quick/content/RabbitMQ%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C.html

  3. 【转载】一起来学Spring Cloud | Eureka Client注册到Eureka Server的秘密

    LZ看到这篇文章感觉写得比较详细,理解以后,便转载到自己博客中,留作以后回顾学习用,喝水不忘挖井人,内容来自于李刚的博客:http://www.spring4all.com/article/180 一 ...

  4. URI--http://zh.wikipedia.org/wiki/%E7%BB%9F%E4%B8%80%E8%B5%84%E6%BA%90%E6%A0%87%E5%BF%97%E7%AC%A6

    维基百科,自由的百科全书     在电脑术语中,统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串. 该种标识允许用户对网络中( ...

  5. 使用OAuth Server PHP实现OAuth2服务

    在现在的网络服务中,OAuth2.0服务已经很普遍了,无论是facebook或者微博的第三方登录,还是手机APP登录,都有很广泛的应用.它主要的目的如下:如果用户的照片在A网站,他想要在B网站使用A网 ...

  6. 树莓派 more

    树莓派 rusthttps://tech.iotcomeon.com/2018/06/tech/deploy/515/sudo curl https://sh.rustup.rs -sSf | sh ...

  7. OAuth 2.0

    国外 OAuth2.0 大全:http://oauth.net/2/ 国内经典:http://www.fising.cn/2011/03/%E4%B8%80%E6%AD%A5%E4%B8%80%E6% ...

  8. 域渗透——获得域控服务器的NTDS.dit文件

    0x00 前言 在之前的文章<导出当前域内所有用户hash的技术整理>曾介绍过通过Volume Shadow Copy实现对ntds.dit文件的复制, 可用来导出域内所有用户hash.本 ...

  9. zabbix 监控java程序

    http://www.tuicool.com/articles/IRnM7f http://transcoder.baidu.com/from=1012852q/bd_page_type=1/ssid ...

随机推荐

  1. split()有个坑

    刚才在做DBMS课程设计的时候遇到了一个以前遇到过的问题不过这次我没有一眼认出来,想了好一会才想起来. 就是在用split()方法来分割路径名字符串的时候,比如 String path = “E:\s ...

  2. 谈谈KV存储集群的设计要点

    版权声明:本文由廖念波原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/150 来源:腾云阁 https://www.qclo ...

  3. 内网安全监控和预警平台架构设想(OSSIM)

    内网安全监控和预警平台架构设想 需求简介 内网安全监控和预警平台是内网安全建设的物质基础,是所有甲方安全建设的必备武器库,无论是应急响应和追踪溯源,还是预知告警.自我清查:做下来总的体会是几个问题永远 ...

  4. Egret5.2.2 微信小游戏行的示例排行榜

    Egret5.2.2版本发布微信小游戏后,在开放数据域有一个默认排行榜.这个文件夹代码+图大小就22kb. 排行榜的效果就是示范用的,很丑...带翻页. 代码如下,基本就是使用canvas渲染了一个排 ...

  5. Windows Phone 独立存储查看器

    1.为了查看我们存放在独立存储的数据,我们需要借助独立存储查看器. 2.简单介绍下,IsoStoreSpy 下载地址:http://download.csdn.net/download/lhb1097 ...

  6. HDCMS常用的一些调用!

    HDCMS常用的一些调用: 头部的标题/描述/关键词的调用: <title><?php if($hdcms['aid']):?><?php if($hdcms['seo_ ...

  7. onethink后台登陆修改验证码!

    验证码: $config = array( 'fontSize' => 30, // 验证码字体大小 'length' => 3, // 验证码位数 'useNoise' => fa ...

  8. 微信开发(3):微信公众号发现金红包功能开发,利用第三方SDK实现(转)

    最近需求是 用户兑换微信红包,需要一些验证,加密,以及证书: 工欲善其事必先利其器 感谢前辈的微信SDK 已经维护三年了,还在维护中! 官方文档走一波 文档还是一如既往的 坑人啊,写的很简单,对简单明 ...

  9. 表格table列宽度控制<colgroup>

    <colgroup> 标签用于对表格中的列进行组合,以便对其进行格式化. 通过使用 <colgroup> 标签,可以向整个列应用样式,而不需要重复为每个单元格或每一行设置样式. ...

  10. debug kibana in chrome

    kibana5.6.5版本 在kibana根目录运行命令:NODE_OPTIONS='--inspect --debug' npm start 也可以尝试命令:NODE_OPTIONS="- ...