基于PHP构建OAuth 2.0 认证平台

在现在的网络服务中,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,也可以用下列命令下载,不过内容都是一样的

Shell

1

2

3

mkdir my-oauth2-walkthrough

cd my-oauth2-walkthrough

git clone https://github.com/bshaffer/oauth2-server-php.git -b master

在这之后配置数据库

SQL

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就知道这个文件是平级的。

server.php

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给客户端

token.php

1

2

3

4

5

// include our OAuth2 Server object

require_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控制器

需要先创建一条记录,来注册一个新的应用

SQL

1

INSERT INTO oauth_clients (client_id, client_secret, redirect_uri) VALUES ("testclient", "testpass", "http://fake/");

然后用命令行调用

Shell

1

curl -u testclient:testpass http://localhost/token.php -d ‘grant_type=client_credentials‘

这里的URL只是示例,实地操作要确定能找到这个token.php
如果运行正常,则显示

JSON

1

{"access_token":"03807cb390319329bdf6c777d4dfae9c0d3b3c35","expires_in":3600,"token_type":"bearer","scope":null}

资源控制器的建立和测试

你创建了Token,你需要在API中测试它,于是你写了如下代码

resource.php

1

2

3

4

5

6

7

8

9

// include our OAuth2 Server object

require_once __DIR__.‘/server.php‘;

// Handle a request for an OAuth2.0 Access Token and send the response to the client

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

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

    die;

}

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

然后运行下面的命令,记得将YOUR_TOKEN替换成刚才得到的token,还有确保URL的正确

Shell

1

curl http://localhost/resource.php -d ‘access_token=YOUR_TOKEN‘

如果没出问题,则会得到下面的结果

JSON

1

{"success":true,"message":"You accessed my APIs!"}

认证控制器的创建和测试

验证控制器是OAuth2的杀手锏,它允许你的平台帮助用户验证第三方应用
它不像第一个例子中直接返回一个Access Token,这里稍微复杂一点

authorize.php

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 object

require_once __DIR__.‘/server.php‘;

$request = OAuth2\Request::createFromGlobals();

$response = new OAuth2\Response();

// validate the authorize request

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

    $response->send();

    die;

}

// display an authorization form

if (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

URL

1

http://localhost/authorize.php?response_type=code&client_id=testclient&state=xyz

你将会看到一个表单,当你选择yes的时候会弹出你所获得的Authorization Code
现在你可以用这个Authorization Code来刚才建立的token.php获得TOKEN,命令如下

Shell

1

curl -u testclient:testpass http://localhost/token.php -d ‘grant_type=authorization_code&code=YOUR_CODE‘

就像刚才一样,你获得了一个TOKEN

Json

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文件

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来完成任务

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‘]}";

时间: 2024-10-11 07:25:09

基于PHP构建OAuth 2.0 认证平台的相关文章

OAuth 2.0 认证的原理与实践

摘要: 使用 OAuth 2.0 认证的的好处是显然易见的.你只需要用同一个账号密码,就能在各个网站进行访问,而免去了在每个网站都进行注册的繁琐过程. 本文将介绍 OAuth 2.0 的原理,并基于 Spring Security 和 GitHub 账号,来演示 OAuth 2.0 的认证的过程. 原文同步至https://waylau.com/principle-and-practice-of-oauth2/ 使用 OAuth 2.0 认证的的好处是显然易见的.你只需要用同一个账号密码,就能在

基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权.基于之前的 IdentityServer3 实现 OAuth 2.0 授权服务[客户端模式(Client Credentials Grant)] 修改. 客户端 public class Clients { public static List<Client> Get() { return ne

基于asp.net MVC 的服务器和客户端的交互(二)之获取Oauth 2.0认证权限

基本Web API的ASP.NET的Oauth2认证 增加Token额外字段 增加Scope授权字段 持久化Token 设计Token的时间间隔 刷新Token后失效老的Token 自定义验证[重启IIS池Token失效,验证权限] Oauth2 认证的流程 客户端发送口令(grant_type,client_id,client_secret)到服务端请求,认证返回access token ,然后客户端跟据获得的access token,根据Access Token获得权限去访问Web API.

OAuth 2.0 认证授权

其实之前自己做的微信服务号的绑定登录也就是个OAuth认证授权 简单看下第三方使用OAuth做认证授权的过程:(取自网络,带图的大家应该都喜欢~) 第一步:用户登录第三方网站,例如使用qq登录. 第二步:点击登录后,会跳到qq平台提示输入用户名和密码. 第三步:如果用户名和密码正确,会提示是否接受授权,如果授权成功,第三方网站就能访问你的资源了,qq头像.用户名等 认证和授权过程(包括三方) 1.服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表. 2.用户,存放在服务提

OAuth 2.0安全案例回顾

转载自:http://www.360doc.com/content/14/0311/22/834950_359713295.shtml 0x00 背景 纵观账号互通发展史,可以发现OAuth比起其它协议(如OpenID)更流行的原因是,业务双方不仅要求账号本身的认证互通(authentication:可理解为“我在双方的地盘姓甚名谁”),而是更需要双方业务流的授权打通(authorization:可理解为“我在双方的地盘上可做什么”),因为后者才能产生实际的互惠互利. 2013年将过大半,有关O

OAuth 2.0 教程

OAuth 2.0 (原文:http://tutorials.jenkov.com/oauth2/index.html) OAuth 2.0 教程 OAuth 2.0 是一个开放的标准协议,允许应用程序访问其它应用的用户授权的数据.例如:一个游戏可以获取Facebook中的用户信息,或者是一个地理位置程序可以获取Foursquare的用户信息等. 这儿是一个示例图: 首先用户进入游戏的web应用,该应用要求用户通过Facebook账户登录,并定向到Facebook的登录界面,用户登录Facebo

基于docker搭建wordpress博客网站平台

WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把 WordPress当作一个内容管理系统(CMS)来使用. WordPress是一款个人博客系统,并逐步演化成一款内容管理系统软件,它是使用PHP语言和MySQL数据库开发的.用户可以在支持 PHP 和 MySQL数据库的服务器上使用自己的博客. WordPress有许多第三方开发的免费模板,安装方式简单易用.不过要做一个自己的模板,则需要你有一定的专业知识.比如你至少要

谈谈基于OAuth 2.0的第三方认证 [下篇]

从安全的角度来讲,<中篇> 介绍的Implicit类型的Authorization Grant存在这样的两个问题:其一,授权服务器没有对客户端应用进行认证,因为获取Access Token的请求只提供了客户端应用的ClientID而没有提供其ClientSecret:其二,Access Token是授权服务器单独颁发给客户端应用的,照理说对于其他人(包括拥有被访问资源的授权者)应该是不可见的.Authorization Code类型的Authorization Grant很好地解决了这两个问题

谈谈基于OAuth 2.0的第三方认证 [上篇]

对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成.具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确认其真实身份.但是这种由Web应用全权负责的认证方式会带来如下两个问题: 对于用户来说,他们不得不针对不同的访问Web应用提供不同的用户凭证.如果这些凭证具有完全不同的密码,我们没有多少人能够记得住,所以对于大部分整天畅游Internet的网友来说,我想他们在不同的网站注册的帐号都会采用相同的密码.密码的共享必然带来安全隐患,因为我们不能