需求
实现三方OAuth2.0授权登录
使用OAuth服务
OAuth 2.0 Server PHP
环境
nginx
mysql
php
框架
Yii
一 安装
项目目录下安装应用
composer.phar require bshaffer/oauth2-server-php "^1.10"
二 构建数据结构
注意 user表需要自定义
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
);
三 代码实现
/**
* Created by PhpStorm.
* User: parker
* Date: 2020/9/8
* Time: 7:08 下午
*
* 使用 OAuth 2.0 Server PHP 搭建三方授权服务
* 相关文档地址 https://bshaffer.github.io/oauth2-server-php-docs/
* 本服务使用 授权码形式
* 授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
* 这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
*
*/
namespace backend\controllers\api;
use common\lib\LController;
use common\lib\LError;
use common\models\admin\AdminModel;
use OAuth2\GrantType\AuthorizationCode;
use OAuth2\Request;
use OAuth2\Response;
use OAuth2\Server;
use OAuth2\Storage\Pdo;
use yii\helpers\Json;
use Yii;
class OauthController extends LController
{
public $enableCsrfValidation = false;
/** @var Pdo $storage */
public $storage;
/** @var Server $server */
public $server;
/** @var Request $request */
public $request;
/** @var Response $response */
public $response;
public function init()
{
$this->storage = new Pdo([
'dsn' => 'mysql:host=10.0.80.10;dbname=ylsrc_admin',
'username' => 'root',
'password' => '2Q5@a5X6fh'
], [
'client_table' => 'src_oauth_clients',
'access_token_table' => 'src_oauth_access_tokens',
'refresh_token_table' => 'src_oauth_refresh_tokens',
'code_table' => 'src_oauth_authorization_codes',
'user_table' => 'src_admin',
'scope_table' => 'src_oauth_scopes',
'public_key_table' => 'src_oauth_public_keys',
]);
$this->server = new Server($this->storage);
$this->request = Request::createFromGlobals();
$this->response = new Response();
}
/**
* 获取授权码(测试使用生产环境服务添加到登录接口)
*
* 获取链接
* GET http://usrc.com/api/oauth/get-code?response_type=code&client_id=1&state=xyz
* response_type 必填 请求类型
* client_id 必填 三方授权id
* state 必填 回调验证字段
*
* 响应方式为跳转到src_oauth_clients表对应id条目设置的redirect_url跳转连接返回第三方应用, 并且携带code
* 示例:对应的redirect_url为 https://host.com 那么对应的跳转连接为(state未使用)
* https://host.com?code=d53d363349951c29593b722a7d2fb05c054f5e65&state=xyz
*
*/
public function actionGetCode()
{
$uid = Yii::$app->user->id;
if($uid){
$this->server->addGrantType(new AuthorizationCode($this->storage)); // or any grant type you like!
$this->server->validateAuthorizeRequest($this->request, $this->response);
$this->server->handleAuthorizeRequest($this->request, $this->response, true, $uid);
$this->response->send();
}else{
$this->ajaxReturn( LError::NO_PERMISSION, LError::getErrMsgByCode( LError::NO_PERMISSION ), [] );
}
}
/**
* 获取access_toke
* 获取链接
* POST http://usrc.com/api/oauth/get-token
* data
* grant_type 必填 请求类型 authorization_code
* client_id 必填 三方授权id
* client_secret 必填 三方授权秘钥
* code 必填 上一步获取的授权码
*
* return
*
* {
* "access_token": "b2d91c2764bdde79e4f1e92349b969e8ee031e8a",
* "expires_in": 3600,
* "token_type": "Bearer",
* "scope": null,
* "refresh_token": "d9293e82c22523ad6500d6b584b484cc3aeb4736"
* }
*/
public function actionGetToken()
{
$response = $this->server->handleTokenRequest($this->request);
$response->send();
}
/**
* 使用token获取用户信息
* 获取连接
* GET http://usrc.com/api/oauth/get-user-info?access_token=b2d91c2764bdde79e4f1e92349b969e8ee031e8a
*
* access_token 上一步获取的token
*
*/
public function actionGetUserInfo()
{
if (!$this->server->verifyResourceRequest($this->request)) {
$this->server->getResponse()->send();
}else{
$token = $this->server->getAccessTokenData($this->request);
$user = AdminModel::findIdentity($token['user_id']);
$data = [
'id' => $user->id,
'username' => $user->account_name,
'mobile' => $user->mobile,
'email' => $user->email,
];
echo Json::encode($data);
}
}
}