热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

php对接AliGenie天猫精灵服务器控制智能硬件esp8266②全面认识第三方授权机制oauth2.0协议,如何在php上搭建oauth2.0服务端!(附带demo)

本系列博客学习由非官方人员半颗心脏潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改


  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

    • 1、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266① 在阿里云购买搭建私有云服务器,配置 SSL 证书 ,做好准备工作!

    • 2、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266② 全面认识第三方授权机制 oauth2.0 协议,如何在 php 上搭建 oauth2.0服务端!

    • 3、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266③渗入熟悉AliGenie 对接协议,揭开第三方云平台是如何让天猫精灵是发送消息到私有服务器的!




文章目录

    • 一、前言;
    • 二、认识`oauth2.0`协议;
    • 三、认识授权过程;
    • 四、开始集成代码;
      • 4.1 数据库初始化;
      • 4.2 我们新建一个给予授权码的代码对外文件`AligenieAuthorize.php`
      • 4.3 我们新建一个给予`access_oken`的代码对外文件`AligenieToken.php`
      • 4.3 我们新建一个给客户端拿着``access_oken``请求资源的对外文件`getResource.php`;
    • 五、测试代码;
    • 六、注意事项;


一、前言;




  • 2018年也就只剩下十天了,今年的收获还是满满的,去年仅仅做了个硬件的MQTT服务器,那今年做了esp8266连接阿里云物联网、京东微联、苏宁智能等,感觉不错!信心杠杠的!!说白了,还是围绕着这个芯片再走,感觉自己能力没有得到很大的提升!明年在硬件领域做esp32的语音功能控制,不再多写esp8266的博文了啦!
  • 今年最大的收获就是可以开发微信小程序以及服务器了,前几天在琢磨这个oauth2.0协议,终于弄懂了原理!而且还用TP5框架搭好了私有云对接天猫精灵云AliGenie,实现不用硬件直连阿里云物联网也可以被天猫精灵控制,哈哈!!
  • 因为天猫精灵云服务器对接需要这个自己云服务器集成oauth2.0服务器端,那么必须要学这个协议的!! 注意是集成oauth2.0服务器端协议!!



二、认识oauth2.0协议;




  • 我开始也是蒙着一头雾水去学这个协议,百度啊搜狗啊,爱奇艺、优酷网址搜索视频学习,东筹西集,终于跑通了!也就认识理解了!大家不懂的玩意,还是要多琢磨几天,就懂了!还是应了那句话“天道酬勤”!!
  • 这协议其实已经广泛被应用了,在我们使用一些网站登录经常遇到,比如下面的迅捷画图网站:
    • 在代码逻辑过程是:迅捷画图网站会提交一则消息到腾讯QQ授权中心网站的认证中心,如果已经在腾讯QQ网站后台注册了,就是展示给用户一个登录界面,当用户操作输入密码或者其他方式登录使得登录成功,则腾讯QQ授权中心网站就会携带当前用户的信息返回给迅捷画图网站!这样就可以实现 迅捷画图网站不知道当前QQ用户登录的账号和密码,也可以获取当前QQ用户的信息,实现登录! 这就是 oauth2.0的强大之处!

在这里插入图片描述



  • 上面是简书网站和腾讯QQ授权中心网站之间的通讯!那么迅捷画图网站就是客户端,而腾讯QQ授权中心网站就是oauth2.0服务器端!换个说法,天猫精灵云服务器就是客户端,我们的服务器就是oauth2.0服务器端
  • 所以,我们就要如何做一个oauth2.0服务器端,这篇文章先不讲解天猫精灵的协议!下篇会讲述哈!记得关注我就好了!



三、认识授权过程;




  • 对于oauth2.0来说,有四种授权方式,但是天猫精灵的授权方式是授权码方式,据说这个授权方式也是最为完整和严密的授权方式,但是我们只能用这个授权方式,那么我们也就理解这个好了:



  1. 授权码模式(authorization code)
  2. 简化模式(implicit)
  3. 密码模式(resource owner password credentials)
  4. 客户端模式(client credentials)



  • 为了更好地记录下整个流程,我这里自己画个图大家理解下!

在这里插入图片描述



  • 需要注意的地方:
    • ①:第一步:在私有云服务器已经注册了一个第三方的客户端的信息(名字 + 密钥),第一步天猫精灵服务器会以oauth2.0标准协议携带这个名字向我们的服务器发起授权请求!
    • ②:第二步:这时候,就是我们服务器要做给用户展示是否授权了,如果授权成功,就把这个授权码+当前的用户信息保存在数据库!,并且把授权码回复给天猫精灵服务器!!
    • ③:第三步:上步骤拿到这个授权码是有有效时间的,就像我们买了的中了奖的彩票一样,不去兑换就会过期无法兑换现金!而这个有效时间是我们私有服务器设置的,默认是30秒!所以,天猫精灵服务器会在30秒内请求我们提供的接口来获取唯一票据凭证access_token!
    • ④:第四步:当我们私有服务器校验这个是在有效时间内请求的话,就会以oauth2.0标准协议发送分配一个唯一票据凭证access_token!给天猫精灵服务器,这时候,天猫精灵每次来发现、控制和查询设备都会携带这个access_token前来操作!
    • 当然,这个access_token也是有有效时间的,天猫精灵服务器推荐为 2天内!



四、开始集成代码;




  • 首先我们从官方提供oauth2.0的集成仓库下载代码:https://github.com/bshaffer/oauth2-server-php !尤其注意,这个最新的代码仓库在php 7.0 版本环境成功,否则会出现没必要的错误!我已经深深踩坑了!

  • 我们仅仅需要oauth2-server-php/src/Oauth2里面的所有文件即可,其他的都是一些测试代码和说明文档!




4.1 数据库初始化;


  • 仓库的代码示范是基于mysql的,这种关系型入门数据库,挺合适的!我们要在我们的项目数据库创建七个表,复制下面的内容,在mysql中创建数据库和表,一个一个添加:


CREATE TABLE oauth_clients (client_id VARCHAR(80) NOT NULL,client_secret VARCHAR(80),redirect_uri VARCHAR(2000),grant_types VARCHAR(80),scope VARCHAR(4000),user_id VARCHAR(80),PRIMARY KEY(client_id)
);CREATE TABLE oauth_access_tokens (access_token VARCHAR(40) NOT NULL,client_id VARCHAR(80) NOT NULL,user_id VARCHAR(80),expires TIMESTAMP NOT NULL,scope VARCHAR(4000),PRIMARY KEY (access_token)
);CREATE TABLE oauth_authorization_codes (authorization_code VARCHAR(40) NOT NULL,client_id VARCHAR(80) NOT NULL,user_id VARCHAR(80),redirect_uri VARCHAR(2000),expires TIMESTAMP NOT NULL,scope VARCHAR(4000),id_token VARCHAR(1000),PRIMARY KEY (authorization_code)
);CREATE TABLE oauth_refresh_tokens (refresh_token VARCHAR(40) NOT NULL,client_id VARCHAR(80) NOT NULL,user_id VARCHAR(80),expires TIMESTAMP NOT NULL,scope VARCHAR(4000),PRIMARY KEY (refresh_token)
);CREATE TABLE oauth_users (username VARCHAR(80),password VARCHAR(80),first_name VARCHAR(80),last_name VARCHAR(80),email VARCHAR(80),email_verified BOOLEAN,scope VARCHAR(4000),PRIMARY KEY (username)
);CREATE TABLE oauth_scopes (scope VARCHAR(80) NOT NULL,is_default BOOLEAN,PRIMARY KEY (scope)
);CREATE TABLE oauth_jwt (client_id VARCHAR(80) NOT NULL,subject VARCHAR(80),public_key VARCHAR(2000) NOT NULL
);

  • 成功创建之后如图:

在这里插入图片描述



  • 我们创建一个第三方应用的名字和密钥,也是后面我们天猫精灵所需要的,也即是在表oauth_clients中插入一个记录,注意redirect_uri的数值必须为固定,grant_types的数值我在官网文档看到是一定要插入的,不然会报错!!
    • client_id–> xuhong
    • client_secret --> xuhongyss123456
    • redirect_uri --> https://open.bot.tmall.com/oauth/callback
    • grant_types --> authorization_code



  • mysql语句:

INSERT INTO oauth_clients (client_id, client_secret, redirect_uri , grant_types ) VALUES ("xuhong", "xuhongyss123456", "https://open.bot.tmall.com/oauth/callback", "authorization_code");



4.2 我们新建一个给予授权码的代码对外文件AligenieAuthorize.php


  • 目的让客户端拿着clientId按照oauth2.0标准协议请求这个文件,拿到授权码!
  • 文件中有一个H5界面界面,展示用户是否授权?

/*** Created by PhpStorm.* User: XuHong* Date: 2018/12/20* Time: 16:00*/require_once('OAuth2/Autoloader.php');
global $server;//根据您的数据库配置而定
$dsn = 'mysql:dbname=db_oauth;host=localhost';
$username = "root";
$password = "root";\OAuth2\Autoloader::register();
//oauth操作数据库开始
$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));\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));
// var_dump($storage);// 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));$request = \OAuth2\Request::createFromGlobals();
$response = new \OAuth2\Response();// 校验请求是否 oauth2.0 请求以及是否 clientId 是否已经注册在数据库
if (!$server->validateAuthorizeRequest($request, $response)) {$response->send();die;
}
// display an authorization form
if (empty($_POST)) {exit('
');
} else {echo 'fail ';
}// print the authorization code if the user has authorized your client
$is_authorized = ($_POST['authorized'] === 'yes');
$server->handleAuthorizeRequest($request, $response, $is_authorized, 2018);
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();



4.3 我们新建一个给予access_oken的代码对外文件AligenieToken.php


  • 如果上面客户端成功拿到授权码,在有效时间内就会来这文件请求拿accessToken


$dsn = 'mysql:dbname=db_oauth;host=localhost';
$username = "root";
$password = "root";\OAuth2\Autoloader::register();
$storage = new \OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));$server = new \OAuth2\Server($storage, array('refresh_token_lifetime' => 2419200,'access_lifetime' => 3600,// 3600 / 60 / 60 = 1 小时有效时间的 accesstoken
));// 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));
$server->handleTokenRequest(\OAuth2\Request::createFromGlobals())->send();



4.3 我们新建一个给客户端拿着access_oken请求资源的对外文件getResource.php;


//资源控制器的建立和测试
require_once('OAuth2/Autoloader.php');global $server;
$dsn = 'mysql:dbname=www_zmdzn_com;host=localhost';
$username = "www_zmdzn_com";
$password = "root";\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));if (!$server->verifyResourceRequest(\OAuth2\Request::createFromGlobals())) {$server->getResponse()->send();die;
}$token = $server->getAccessTokenData(\OAuth2\Request::createFromGlobals());//如果通过校对,则打印该 token对应的用户
echo json_encode(array('success' => true, 'message' => 'the token is right and your user_id is ' . $token['user_id']));//do your things



五、测试代码;


  • 第一步:我们先oauth2.0协议向服务器请求授权码,下面的域名根据您的情况而定!看请求参数有指定response_typecode,而client_id就是我们在数据库插入的那个数值,后面那个state其然就是加密方式什么的。我也不太清楚!

https://www.domain.com/AligenieAuthorize.php?response_type=code&client_id=xuhong&state=0.125544

  • 不出意外,出现如下界面?先询问用户是否授权,然后得到一串字符,就是授权码!
    在这里插入图片描述



  • 第二步:上一步,我们已经成功拿到了授权码,此刻我们以oauth2.0协议拿着这个授权码去请求access_token,下面是我在postMan工具模拟的,注意要在Authorization这一栏的Basic Oauth填入我们的数据库的那个记录的信息。之后在body里面填入我们的授权方式grant_typeauthorization_code,而code就是上面拿到的那个授权码! 成功之后,会得到以下数据:

{"access_token": "54a7cab857d46c15c877b469b78e56ac4b3670be","expires_in": 3600,"token_type": "Bearer","scope": null,"refresh_token": "6325ef3783e9495cfc6147640655690ce2ee180c"
}

在这里插入图片描述



  • 第三步:上一步我们已经拿到了access_token,这步我们就拿这个access_token去拿资源啦!

https://www.domain.com/getResource.php?access_token=54a7cab857d46c15c877b469b78e56ac4b3670be

在这里插入图片描述



六、注意事项;


  • 整个过程中,我们都发现到最后都是拿这个access_token,这个信息是至关重要的,后面的天猫精灵都是拿着这个来请求控制或者查询设备的!
  • 还要强调一点,环境一定要php7.0版本或以上,这个新版的仓库代码兼容不了旧版的,我已经尝试了一天了!
  • 大家有什么问题,欢迎留言!
  • 本代码工程下载(包括oauth2.0库):https://download.csdn.net/download/xh870189248/10866543

推荐阅读
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 标题: ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
author-avatar
拥有勒幷不代表幸福_563
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有