使用OAuth Server PHP实现OAuth2服务
在现在的网络服务中,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']}"; |
使用OAuth Server PHP实现OAuth2服务的更多相关文章
- 3行代码快速实现Spring Boot Oauth2服务
这里的3行代码并不是指真的只需要写3行代码,而是基于我已经写好的一个Spring Boot Oauth2服务.仅仅需要修改3行数据库配置信息,即可得到一个Spring Boot Oauth2服务. 项 ...
- 轻松搭建CAS 5.x系列(6)-在CAS Server上增加OAuth2.0协议
概述说明 CAS Server默认搭建出来,客户端程序只能按照CAS自身的协议接入.CAS的强大在于,有官方的插件,可以支持其他的协议.本章节就让CAS Server怎么增加OAuth2.0的登录协议 ...
- ArcGIS API for JavaScript(2)-ArcGIS Server发布要素图层服务
1.前言 上一篇该系列的文章我们主要讲了一下基础Web地图搭建,这篇我们主要讲一下ArcGIS Server发布服务,并且如何调用服务.将自己的数据加载到Web地图当中来,实现Web端浏览数据. 2. ...
- Atitit Server Side Include ssi服务端包含规范 csi esi
Atitit Server Side Include ssi服务端包含规范 csi esi 一.CSI (Client Side Includes) 1 1.1. 客户端包含1 1.2. Ang ...
- ArcGIS Server新建主题图服务的步骤
ArcGIS Server新建主题图服务的步骤: 1.修改数据库模型图(PowerDesigner) 2.修改lygis.gdb文件数据库(发布时可以快速把表结构从gdb数据库拷贝到客户服务器的SDE ...
- 以Server模式启动Derby服务竟然抛套接字权限异常
以Server模式启动Derby服务竟然抛套接字权限异常:access denied ("java.net.SocketPermission" "localhost:15 ...
- OpenLayers调用arcgis server发布的地图服务
有两种方式可以调用arcgis server发布的地图服务,一种是rest,一种是wms. 地图的投影为900913,arcgis server为10.0版本,地图服务的空间参考为3857. 与 ...
- OpenLayers调用ArcGIS Server发布的WFS服务
OpenLayers调用ArcGIS Server发布的WFS服务 原创: 蔡建良 2013-08-20 一. 开发环境 1) Openlayers2.13+arcgis server9.3 2) W ...
- 异步tcp通信——APM.Server 消息推送服务的实现
消息推送服务 服务器推送目前流行就是私信.发布/订阅等模式,基本上都是基于会话映射,消息对列等技术实现的:高性能.分布式可以如下解决:会话映射可采用redis cluster等技术实现,消息对列可使用 ...
随机推荐
- 解决 slf4j + log4j 在云服务上打印乱码
由于云服务器的环境是纯英文的 虽然在eclipse中可以打印日志显示中文,但是实用putty的时候查看却是乱码,下载日志也同样是乱码 那么只要设置utf-8即可
- [jk]服务器远控卡及kvm切换器
远控卡的需求 经常我们有这么一个需求,那就是某一台器服务器突然宕机,不能启动,而机房却在外地.解决这个问题的方法有两种,一是联系机房人员,二是通过idrac卡远程连接.我们必须根据事情的轻重缓急,来选 ...
- Android 微信支付资料收集
老板要求支持微信支付,收集了些资料做后期参考 http://www.360doc.com/content/15/0214/10/7044580_448519997.shtml http://www.t ...
- Ubuntu 14.04环境变量修改
因在开发编译时是找不到命令,原因是将路径添加到环境变量,如何设置环境变量,搜索一下,找到以下关于环境变量设置的几个文件及何时执行. 首先要认识几个和环境变量有关的文件: /etc/profile —— ...
- Java SWT编程基础
SWT常用组件列表及使用 https://blog.csdn.net/u013310025/article/details/52939452 SWT编程基础-控件和图形资源 https://blog. ...
- RabbitMQ基础组件和SpringBoot整合RabbitMQ简单示例
交换器(Exchange) 交换器就像路由器,我们先是把消息发到交换器,然后交换器再根据绑定键(binding key)和生产者发送消息时的路由键routingKey, 按照交换类型Exchange ...
- Delphi中的三目运算函数有哪些?(XE10.2+WIN764)
相关资料:https://www.cnblogs.com/rogge7/p/6078903.html 问题现象:在做一个判断时突然想到了C++的三目运算,就在想Delphi中一共有几个? 问题处理: ...
- 4. 集成学习(Ensemble Learning)Adaboost
1. 集成学习(Ensemble Learning)原理 2. 集成学习(Ensemble Learning)Bagging 3. 集成学习(Ensemble Learning)随机森林(Random ...
- C# Null 赋值
在此之前,我们先看一段程序: class Program { static void Main(string[] args) { Childre ...
- iOS APP版本更新跳转到App Store下载/更新方法
使用下面的连接即可跳转到App Store itms-apps://itunes.apple.com/cn/app/id*********** 其中********* ...