本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。
1、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266① 在阿里云购买搭建私有云服务器,配置 SSL 证书 ,做好准备工作!
2、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266② 全面认识第三方授权机制 oauth2.0 协议,如何在 php 上搭建 oauth2.0服务端!
3、 php对接AliGenie天猫精灵服务器控制智能硬件esp8266③渗入熟悉AliGenie 对接协议,揭开第三方云平台是如何让天猫精灵是发送消息到私有服务器的!
MQTT
服务器,那今年做了esp8266
连接阿里云物联网、京东微联、苏宁智能等,感觉不错!信心杠杠的!!说白了,还是围绕着这个芯片再走,感觉自己能力没有得到很大的提升!明年在硬件领域做esp32
的语音功能控制,不再多写esp8266
的博文了啦!oauth2.0
协议,终于弄懂了原理!而且还用TP5
框架搭好了私有云对接天猫精灵云AliGenie
,实现不用硬件直连阿里云物联网也可以被天猫精灵控制,哈哈!!oauth2.0
服务器端,那么必须要学这个协议的!! 注意是集成oauth2.0
服务器端协议!!oauth2.0
协议;oauth2.0
的强大之处!oauth2.0
服务器端!换个说法,天猫精灵云服务器就是客户端,我们的服务器就是oauth2.0
服务器端oauth2.0
服务器端,这篇文章先不讲解天猫精灵的协议!下篇会讲述哈!记得关注我就好了!oauth2.0
来说,有四种授权方式,但是天猫精灵的授权方式是授权码方式,据说这个授权方式也是最为完整和严密的授权方式,但是我们只能用这个授权方式,那么我们也就理解这个好了:oauth2.0
标准协议携带这个名字向我们的服务器发起授权请求!授权码
+当前的用户信息保存在数据库!,并且把授权码回复给天猫精灵服务器!!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
里面的所有文件即可,其他的都是一些测试代码和说明文档!
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");
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();
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();
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_type
为code
,而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_type
为authorization_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
版本或以上,这个新版的仓库代码兼容不了旧版的,我已经尝试了一天了!