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)
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,也可以用下列命令下载,不过内容都是一样的
|
1
2
3
|
mkdir my-oauth2-walkthroughcd my-oauth2-walkthroughgit clone https://github.com/bshaffer/oauth2-server-php.git -b master |
在这之后配置数据库
|
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就知道这个文件是平级的。
|
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给客户端
|
1
2
3
4
5
|
// include our OAuth2 Server objectrequire_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控制器
需要先创建一条记录,来注册一个新的应用
|
1
|
INSERT INTO oauth_clients (client_id, client_secret, redirect_uri) VALUES ("testclient", "testpass", "http://fake/"); |
然后用命令行调用
|
1
|
curl -u testclient:testpass http://localhost/token.php -d 'grant_type=client_credentials' |
这里的URL只是示例,实地操作要确定能找到这个token.php
如果运行正常,则显示
|
1
|
{"access_token":"03807cb390319329bdf6c777d4dfae9c0d3b3c35","expires_in":3600,"token_type":"bearer","scope":null} |
资源控制器的建立和测试
你创建了Token,你需要在API中测试它,于是你写了如下代码
|
1
2
3
4
5
6
7
8
9
|
// include our OAuth2 Server objectrequire_once __DIR__.'/server.php';// Handle a request for an OAuth2.0 Access Token and send the response to the clientif (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) { $server->getResponse()->send(); die;}echo json_encode(array('success' => true, 'message' => 'You accessed my APIs!')); |
然后运行下面的命令,记得将YOUR_TOKEN替换成刚才得到的token,还有确保URL的正确
|
1
|
curl http://localhost/resource.php -d 'access_token=YOUR_TOKEN' |
如果没出问题,则会得到下面的结果
|
1
|
{"success":true,"message":"You accessed my APIs!"} |
认证控制器的创建和测试
验证控制器是OAuth2的杀手锏,它允许你的平台帮助用户验证第三方应用
它不像第一个例子中直接返回一个Access Token,这里稍微复杂一点
|
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 objectrequire_once __DIR__.'/server.php';$request = OAuth2\Request::createFromGlobals();$response = new OAuth2\Response();// validate the authorize requestif (!$server->validateAuthorizeRequest($request, $response)) { $response->send(); die;}// display an authorization formif (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
|
1
|
|
你将会看到一个表单,当你选择yes的时候会弹出你所获得的Authorization Code
现在你可以用这个Authorization Code来刚才建立的token.php获得TOKEN,命令如下
|
1
|
curl -u testclient:testpass http://localhost/token.php -d 'grant_type=authorization_code&code=YOUR_CODE' |
就像刚才一样,你获得了一个TOKEN
|
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文件
|
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来完成任务
|
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了,
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)的更多相关文章
- 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 ...
- 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
- 【转载】一起来学Spring Cloud | Eureka Client注册到Eureka Server的秘密
LZ看到这篇文章感觉写得比较详细,理解以后,便转载到自己博客中,留作以后回顾学习用,喝水不忘挖井人,内容来自于李刚的博客:http://www.spring4all.com/article/180 一 ...
- 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)是一个用于标识某一互联网资源名称的字符串. 该种标识允许用户对网络中( ...
- 使用OAuth Server PHP实现OAuth2服务
在现在的网络服务中,OAuth2.0服务已经很普遍了,无论是facebook或者微博的第三方登录,还是手机APP登录,都有很广泛的应用.它主要的目的如下:如果用户的照片在A网站,他想要在B网站使用A网 ...
- 树莓派 more
树莓派 rusthttps://tech.iotcomeon.com/2018/06/tech/deploy/515/sudo curl https://sh.rustup.rs -sSf | sh ...
- 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% ...
- 域渗透——获得域控服务器的NTDS.dit文件
0x00 前言 在之前的文章<导出当前域内所有用户hash的技术整理>曾介绍过通过Volume Shadow Copy实现对ntds.dit文件的复制, 可用来导出域内所有用户hash.本 ...
- zabbix 监控java程序
http://www.tuicool.com/articles/IRnM7f http://transcoder.baidu.com/from=1012852q/bd_page_type=1/ssid ...
随机推荐
- 走进ELK原理
日志的分析在联调和后期维护是非常重要. 今天让我们进入ELK...让我们一起感受这个强大的日志收集,日志分析存储,日志查询界面化显示的震撼效果吧. Elasticsearch是个开源分布式搜索引擎,它 ...
- 【RF库Collections测试】combine lists
Arguments: [ *lists ]Combines the given `lists` together and returns the result. The given lists are ...
- json 数据分析
/* 健一健康头条 */ try { String url = "http://www.j1health.com/j1api.php/index/getJ1healthHotLists&qu ...
- INSTALL_FAILED_INVALID_APK
在项目中无意中把APP只写成了 xxx 没有xxx.xxx.xxx 掉坑里了,找了好久,给大家提不醒
- 如何让IOS中的文本实现3D效果
本转载至 http://bbs.aliyun.com/read/181991.html?spm=5176.7114037.1996646101.25.p0So7c&pos=9 zh ...
- Android 内存使用hprof文件打开方法
http://blog.csdn.net/moruihong/article/details/7677128 与C++的内存不同,C++的内存泄露是由于分配了内存给某程序但是又没有回收造成的.Java ...
- node中的对象
1. class的概念 定义一个class,属性都是private,方法都是public. Hello.js: 使用class index.js: 2. 单例类 使用exports而不是module. ...
- Windows Phone 7 检查手机网络
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Wi ...
- android系统自带图标
android:src="@android:drawable/ic_media_rew"
- mysql动态sql 整理多个字段
原始表: 整理后的表: 方案一(动态sql): BEGIN #Routine body goes here... DECLARE v1 ); DECLARE v2 ); #DECLARE v3 VAR ...