PHP oauth2.0框架,搭建OAuth2.0

龚勇锐
2023-12-01

前奏

系统:Ubuntu

语言:PHP7

框架:YAF

OAuth2.0:bshaffer/oauth2-server-php

OAuth2.0 有很多开源代码库

Github 排名前两位

thephpleague/oauth2-server

bshaffer/oauth2-server-php

本文使用的是第二个:bshaffer。原因:使用简单,可以很快上手,文档齐全,功能完善。

引入 OAuth2.0 的 Server 端源代码

编辑 Composer.json 文件

{

"require": {

"bshaffer/oauth2-server-php" : "v1.10.0"

}

}

yaf框架结构

├── application

│ └── modules

│ └── User

│ ├── controllers

│   │ └── Oauth.php

│ └── views

│ └── oauth

│ ├── authorize.php

│ ├── auth.php

│ ├── index.php

│ └── resource.php

├── Bootstrap.php

├── cli

├── composer.json

├── composer.lock

├── composer.phar

├── conf

├── docs

├── public

└── vendor

Yaf 框架中,在 Bootstrap.php 文件中自动加载 OAuth2.0

public function _initLoader(Yaf_Dispatcher $dispatcher)

{

include(APP_PATH . '/vendor/autoload.php');

}

新建一个 Controller 文件:Oauth.php,在里面建立几个 Action

AuthorizeAction() 服务端:提供授权

TokenAction() 服务端:提供Token

ResourceAction() 服务端:提供资源

IndexAction() 客户端:模拟第三方接入

_server() 服务端:初始化服务器相关,如:存储,这里采用mysql

命名空间

use OAuth2\Server;

use OAuth2\Storage\Pdo;

use OAuth2\GrantType\AuthorizationCode;

use OAuth2\GrantType\ClientCredentials;

use OAuth2\GrantType\UserCredentials;

use OAuth2\Request;

use OAuth2\Response;

_server() 函数代码

private function _server()

{

$dbParams = array(

'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=oauth;charset=utf8;',

'username' => 'root',

'password' => '123456',

);

// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"

$storage = new Pdo($dbParams);

// Pass a storage object or array of storage objects to the OAuth2 server class

$server = new Server($storage);

// Add the "Client Credentials" grant type (it is the simplest of the grant types)

$server->addGrantType(new ClientCredentials($storage));

// Add the "Authorization Code" grant type (this is where the oauth magic happens)

$server->addGrantType(new AuthorizationCode($storage));

return $server;

}

IndexAction() 代码

public function indexAction()

{

$uri = $_SERVER['QUERY_STRING'];

$code = substr($uri, strpos($uri, 'code=')+5, 40);

$state = substr($uri, strpos($uri, 'state=')+6);

if ($code) {

$params = array(

'code' => $code,

'state' => $state,

'client_id' => 'client_id',

'client_secret' => 'client_secret',

'grant_type' => 'authorization_code',

'scope' => 'basic',

'redirect_uri' => 'http://yourhost/user/oauth/index',

);

$url = 'http://yourhost/user/oauth/token';

$result = $this->httpPost($url, $params);

$result = json_decode($result, true);

//写入Session,便于测试

Yaf_Session::getInstance()->set('access_token',$result['access_token']);

return false;

} else {

//客户端请求授权之前,页面中展示一个链接,用户点后,可以跳转至服务端的授权页面。

$this->getView()->assign('data', array())->render('oauth/index.php');

}

}

对应的模板代码:oauth/index.php

AuthorizeAction() 代码

/**

* 展示授权页面,用户可以点击同意进行授权

*/

public function AuthorizeAction()

{

$request = Request::createFromGlobals();

$is_authorized = $request->request('is_authorized') ? true : false;

//判断用户是否同意授权

if ($is_authorized) {

$response = new Response();

$server = $this->_server();

// validate the authorize request

if (!$server->validateAuthorizeRequest($request, $response)) {

$response->send();

die;

}

$server->handleAuthorizeRequest($request, $response, $is_authorized)->send();

return false;

}

//将请求授权中带来的各个参数,写入授权页中的变量,用以授权表单POST提交。

$renderData = $_GET;

$this->getView()->assign('data', $renderData)->render('oauth/authorize.php');

}

用户授权页面:oauth/authorize.php

直达天庭 - 南天门

src="https://upload.api.weibo.com/square/aa397b7fgw1f556jk3z3bj20280283yc.jpg"

alt="app">

人间

凡人

http://app.weibo.com/t/feed/324Mrt
有 1 个你关注的人连接

将允许 人间进行以下操作:
  • 获得你的个人信息,好友关系

  • 分享内容到你的微博

  • 获得你的评论

$(document).ready(function(){

$(".WB_btn_link").click(function(){

$("#authZForm").submit();

});

})

TokenAction()

/**

* 返回JSON结构数据

* {

access_token: "977b1077556e9b23ff07ef7606a5eaf947f27d41",

expires_in: 3600,

token_type: "Bearer",

scope: "basic",

refresh_token: "d2367887bdd743121adfe5fda5083064439f1cb1"

}

*/

public function TokenAction()

{

$server = $this->_server();

$server->handleTokenRequest(Request::createFromGlobals())->send();

return false;

}

ResourceAction() 代码

public function ResourceAction()

{

$server = $this->_server();

//获取授权用户Session中保存的access_token,用access_token可以请求权限范围内的所有接口

$_POST['access_token'] = Yaf_Session::getInstance()->get('access_token');

// Handle a request to a resource and authenticate the access token

if (!$server->verifyResourceRequest(Request::createFromGlobals())) {

$server->getResponse()->send();

die;

}

echo json_encode(array('success' => true, 'message' => 'You accessed my APIs!'));

return false;

}

请求用户资源:/user/oauth/resource

{

success: true,

message: "You accessed my APIs!"

}

实现思路:

URL请求:/user/oauth/index,Client端

对应的模板里放置一个链接,用以跳转至服务端的授权认证页面/user/oauth/authorize。授权成功后,服务端会将对应的code和state参数,附在回调的redirect_uri里,即:/user/oauth/index?code=fcd6a9589e7ab43398e4e5349b23846babc79fab&state=xxx,在indexAction中解析出回调的code,用以请求接口/user/oauth/token,来交换access_token。

URL请求:/user/oauth/authorize,Server端

对应的模板里是告知用户,即将授予的权限列表,以及是否允许授权的按钮。

URL请求:/user/oauth/token,Server端

获取access_token。

URL请求:/user/oauth/resource,Server端

获取用户资源

LAST:

各种授权类型,都可以很方便支持。

数据存储层,也可以随意切换,比如切换为 Redis

 类似资料: