`

一步一步搭建 OAuth 认证服务器

阅读更多
现在越来越多开放的互联网公司提供对外的 API 接口,使得第三方应用开发人员可以开发基于该平台接口的应用程序。国外有Twitter、Flicker Service等;国内的,像腾讯微博开放平台、新浪微博开放平台等等。

这些平台接口的认证方式,无一例外的,都采取了 OAuth 来实现(Twitter原来使用的是Basic Auth方式,后来全面转向OAuth)。

那么,OAuth 是什么?OAuth认证又有什么好处呢?

OAuth 是什么

关于OAuth的定义,在 OAuth官网 的首页上,有一行大大的文字说明:

PHP

1
An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.
(OAuth) 是一个开放协议,它以一种简单、标准的方式实现对桌面和 Web 的应用程序的安全 API 认证。

OAuth 1.0 协议(中文版 | 英文版)这样介绍OAuth:“OAuth 协议致力于使网站和应用程序(统称为消费方)能够在无须用户透露其认证证书的情况下,通过 API 访问某个web服务(统称为服务提供方)的受保护资源。更一般地说,OAuth 为 API 认证提供了一个可自由实现且通用的方法”。

关于 OAuth 的用途,OAuth 1.0 协议(中文版 | 英文版)上举了一个例子:某打印服务提供商 printer.example.com(消费方),希望在无须用户提供其照片存储站点密码的情况下,访问用户储存在 photos.example.net(服务提供方)上的个人照片。

假如没有 OAuth,用户必须要向消费方也就是 printer 提供自己在服务提供商 photos 上的授权资料(通常是密码),消费方利用这个授权资料,通过服务提供方的权限验证,从而获得要打印的图片。这样看似没有什么问题。但是用户的授权资料,通常在这一过程中被消费方有意或者无意地窃取或泄露,从而对用户和服务提供方的信息安全造成威胁。

而如果利用 OAuth 进行此过程的授权,用户的授权资料并不会传递给第三方(也就是消费方,通常是App应用),而消费方只需要将用户引导至服务提供方的授权页面进行授权,使得消费方获得访问受限资源的权限即可。而在此过程中,用户授权过程是在服务提供方进行的,消费方并不会直接接触到用户的授权资料,因此一般不会造成用户授权资料的泄密,从而既保证了用户和服务提供方的信息安全,又使得消费方完成了对受限资源的读取。可谓一举三得。

个人对 OAuth 授权过程的理解:服务提供方 SP 好比一个封闭院子,只有持卡人才能进入,用户 U 就是持卡人之一。而消费方 C 没有持卡,通常情况下是不能进入的。但是有一天,由于特殊原因,U 需要 C 帮忙去 SP 那里取一样东西。这个时候问题就来了:  C 没有持卡,不能进去院子,而 U 又不能把卡直接给 C (卡上面有很多个人机密信息,不方便外泄哦)。怎么办呢?

哦,对了,U 可以带着 C 去门口,告诉SP:这个人是我认识的,他需要进去帮我拿我的一样东西,请予放行。这样,U 既不用将带有个人私密信息的门卡交给 C,C 也通过验证拿到了属于 U 的东西。

有的人要问了,是不是下次 C 想要再进 SP 的拿 U 的东西的话,是不是就不用 U 的指引了呢?人类社会的情况通常是这样的。可惜,在 HTTP 的世界里,由于 HTTP 是无状态的协议,因此,SP 仍然不会认识 C。所以,每次 C 想要取东西,总是需要 U 的指引。是不是很麻烦呢?呵呵。但是为了安全,麻烦一点又有什何妨!

上面介绍了 OAuth 认证的基本思路,如果你还不理解,可以参考 OAuth认证流程图, 或者查看腾讯微博关于OAuth认证的介绍。OAuth 官方网站就有一篇文档教程《OAuth入门指南》,不过没有中文版本。有兴趣同学的也可以自己看看。

OAuth 认证授权有以下几个特点:

1. 简单:不管是 OAuth 服务提供者还是应用开发者,都很容易于理解与使用;
2. 安全:没有涉及到用户密钥等信息,更安全更灵活;
3. 开放:任何服务提供商都可以实现 OAuth,任何软件开发商都可以使用 OAuth;
那么下面我们就作为服务提供商角色,来实现 OAuth 认证服务器的安装和搭建。

其实,很多先行者已经开发出了很多的 OAuth 消费方代码(客户端)和服务提供方代码(服务端),这里是它们的一些列表,其中包含了 .NET (C#/VB.NET), ColdFusion, Java, Javascript, Jifty, Objective-C, OCaml, Perl, PHP, Python, Ruby, Erlang 和其他语言的一些实现。

通过 Google,我找到了一个开源的 OAuth 服务端代码和消费方开源代码库项目——oauth-php. 我们就借此来实现。关于OAuth,项目主页的介绍是: OAuth Consumer And Server Library For PHP. 它包含一个完整实现的可扩展的OAuth存储,支持 MySQL/MySQLi,  Postgresql,  PDO 和 Oracle 等多种存储方式。

它实现了以下方法:

认证进来的请求
为出去的请求签名
使用 body 为请求签名
为多用户管理消费方的 key 和 token(服务端和消费端)
记录经过类库处理的进出的请求(可以在数据库中进行可选配置)
很多网站都在使用oauth-php, 包括荷兰阿姆斯特丹Mediamatic Lab实验室出品的anyMeta CMS. 目前,oauth-php 的代码主要由Corollarium Technologies 负责维护。

为你的服务器增加 OAuth 非常简单。你需要检查进来的请求中 OAuth 认证细节。首先,我们需要四个控制器 controller 文件:

oauth_register.php 使消费方用户获得 key 和密钥
request_token.php 返回一个未认证的 request token
authorize.php 认证一个request token
access_token.php 将认证后的 request token 置换为 access token
以下的例子,假设使用的数据存储器是MySQL。你也可以使用其他数据库——当你第一次使用 OAuthStore 实例的时候指定一个参数,告诉它你要使用的数据库。

PHP

1
$store = OAuthStore::instance('mystore');
这就是假设在存储器目录,你有一个名为 OAuthStoremystore.php 文件。在这里我们使用 OAuthStoreMySQL.php 文件来实现。这也就是说,我们在实例化 OAuthStore 的时候,需要这样做:

PHP

1
$store = OAuthStore::instance('MySQL');
然后,在每个请求被处理之前,都可以检查其是否带有 OAuth 认证信息:

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
if (OAuthRequestVerifier::requestIsSigned())
{
        try
        {
                $req = new OAuthRequestVerifier();
                $user_id = $req->verify();

                // 如果存在 user_id, 那么作为那个用户角色登录(对于本次请求)
                if ($user_id)
                {
                        // **** 在这里新增你的代码 ****
                }
        }
        catch (OAuthException $e)
        {
                // 请求已经签名,但是认证失败
                header('HTTP/1.1 401 Unauthorized');
                header('WWW-Authenticate: OAuth realm=""');
                header('Content-Type: text/plain; charset=utf8');

                echo $e->getMessage();
                exit();
        }
}
每个消费方都使用 key 和密钥的组合和 token 和 token 密钥的组合来为它的请求进行签名。而在此之前,消费方必须要先获取属于它的消费方 key 和消费方密钥。 oauth_register.php 就是负责分发消费方 key 和密钥的控制器文件。

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
// 当前登录用户
$user_id = 1;

// 下面的内容应该来自用户填写的表单
$consumer = array(
    // 下面两个是必须的
    'requester_name' => 'John Doe',
    'requester_email' => 'john@example.com',

    // 下面的是可选的
    'callback_uri' => 'http://www.myconsumersite.com/oauth_callback',
    'application_uri' => 'http://www.myconsumersite.com/',
    'application_title' => 'John Doe\'s consumer site',
    'application_descr' => 'Make nice graphs of all your data',
    'application_notes' => 'Bladibla',
    'application_type' => 'website',
    'application_commercial' => 0
);

// 注册消费方
$store = OAuthStore::instance();
$key   = $store->updateConsumer($consumer, $user_id);

// 从数据存储器获得完整的消费方信息
$consumer = $store->getConsumer($key);

// 消费方用户将需要 key 和 secret
$consumer_id = $consumer['id'];
$consumer_key = $consumer['consumer_key'];
$consumer_secret = $consumer['consumer_secret'];
如果你想要更新之前注册的消费方身份,提供消费方id,key 和 secret 。key 和 secret 在更新操作完成之前不会进行改变。

你还可以请求一个特定用户注册的所有消费方列表:

PHP

1
2
3
4
5
6
// 当前登录用户
$user_id = 1;

// 取得这个用户注册的全部消费方列表
$store = OAuthStore::instance();
$list = $store->listConsumers($user_id);
request_token.php 这个控制器文件负责返回请求 token(未认证的 request token)。当消费方获取了 key 和 secret 之后,它就可以向服务器端请求未认证的 request token 了:

PHP

1
2
3
$server = new OAuthServer();
$token = $server->requestToken();
exit();
authorize.php 控制器文件负责认证一个用户请求 token。这个控制器负责询问用户是否允许消费方访问他的账户。如果允许,那么消费方将可以使用 request token 换取 access token。必须要保证用户在访问下面的代码之前是登录状态。OAuthServer 服务器使用 SESSION 存储一些 OAuth 状态信息,所以必须要开启seesion会话(要么是 session_start 函数,要么就是自动开启)。

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
31
32
// 当前登录用户
$user_id = 1;

// 取得OAuth存储器和OAtuh服务器对象
$store  = OAuthStore::instance();
$server = new OAuthServer();

try
{
    // 检查当前请求中是否包含合法的request token
    // 返回一个包含消费方key, 消费方secret, token, token secret 和 token 类型的数组.
    $rs = $server->authorizeVerify();

    if ($_SERVER['REQUEST_METHOD'] == 'POST')
    {
        // 检查用户是否点击了 'allow' 按钮或者其他你指定的按钮)
        $authorized = array_key_exists('allow', $_POST);

        // 设置 request token 的认证状态(已认证或者是未认证)
        // 当包含 oauth_callback 回调的时候,这些将传给消费方
        $server->authorizeFinish($authorized, $user_id);

        // 没有 oauth_callback 回调, 显示认证结果

        // ** 你的代码 **
   }
}
catch (OAuthException $e)
{
    // 没有需要认证的 request token, 显示一个可以输入 request token 的页面
    // ** 你的代码 **
}
access_token.php 控制器文件负责将认证的request token换成access token。access token 可以被用来为请求签名。

PHP

1
2
$server = new OAuthServer();
$server->accessToken();
看完本文,如果还是一头雾水,不知道如何下手,可以继续阅读《基于PHP & MySQL 搭建 OAuth Server》。

http://www.fising.cn/2011/03/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E6%90%AD%E5%BB%BA-oauth-%E8%AE%A4%E8%AF%81%E6%9C%8D%E5%8A%A1%E5%99%A8.shtml
http://blog.sina.cn/dpool/blog/s/blog_4b82753d0100yk9s.html?
分享到:
评论

相关推荐

    spring-oauth-server

    本文将详细介绍如何使用Spring和OAuth2搭建一个认证服务器。 ### 一、项目概述 `spring-oauth-server` 是一个基于Spring框架和OAuth2构建的认证服务示例。它包含了完整的源代码和SQL脚本,方便开发者快速上手并...

    springboot 微信端登录demo.rar

    Spring Boot是由Pivotal团队提供的全新框架,旨在简化Spring应用的初始搭建以及开发过程。它预设了各种默认配置,减少了大量的XML配置,使得开发人员可以快速构建基于Spring的应用。 微信端登录涉及到的主要技术点...

    springcloud 案例

    3. **自定义权限认证**:这一步通常涉及到Spring Security或OAuth2。你可以创建一个认证服务,处理用户的登录验证,然后使用JWT(JSON Web Tokens)生成令牌,传递给其他微服务进行权限校验。每个微服务在接收到请求...

    android 微博

    - **安全考虑**:了解并实施OAuth2或其他认证机制,确保用户数据的安全。 5. **网络通信**: - **HTTP请求库**:使用像Retrofit或Volley这样的库发送HTTP请求,与服务器进行数据交换。 - **JSON解析**:使用Gson...

    SSO实例安装和配置指南

    SSO系统通常包含两个主要部分:认证服务器(Identity Provider, IDP)和资源服务提供商(Service Provider, SP)。IDP负责用户的认证,而SP则依赖于IDP的认证结果来授权用户访问其服务。 1. **安装SSO实例** - **...

    Liferay门户手册.pdf

    这一过程通常涉及到配置Liferay以使用LDAP服务器进行身份验证,可能需要调整Liferay的配置文件以适应LDAP服务器的特定设置。 ##### 4.4 集成应用安全单点登录 单点登录(Single Sign-On,SSO)允许用户在一个应用中...

    PHP开发QQ第三方登录功能 实战视频课程

    - 主要功能:提供包括登录认证、数据统计分析等在内的多种服务。 - 适用场景:适用于各种类型的网站和移动应用。 2. **注册应用流程**: - 访问QQ开放平台官网进行注册。 - 提交基本信息,如应用名称、Logo、...

    兔子影视网站源码v1.3.6.5微信电影网站基于freekan影视系统二次开发.txt

    此功能涉及到OAuth2.0认证机制的学习与实践,包括但不限于获取授权码、访问令牌等步骤。 2. **二次开发定制化**:在`freekan`基础上进行二次开发意味着开发者可以根据具体需求对原有功能进行修改或扩展。例如增加...

    EStoree源代码

    5. **安全机制**:包括用户认证(如OAuth、JWT)、支付安全(如SSL加密、第三方支付平台集成)和防止SQL注入、XSS攻击的安全措施。 6. **部署配置**:涉及服务器环境搭建、负载均衡、日志管理和持续集成/持续部署(C...

    在线购物系统项目计划书与需求文档

    为了达到这些目标,开发者需要了解SSL/TLS加密、OAuth认证、支付网关集成以及可用性设计原则。 最后,文件名称“软件工程2009”可能暗示这是一个历史项目或教程,展示了早期的软件工程实践。尽管技术日新月异,但...

    CAS restful接口调用

    CAS支持多种认证协议,包括但不限于HTTP Basic、HTTP Form-Based、OAuth等。本文将重点介绍CAS如何通过RESTful接口来实现票据的获取与验证过程。 #### 二、环境搭建 为了使用CAS提供的RESTful接口功能,首先需要在...

    本地会员与新浪微博api绑定和同步登陆(文件 数据库 教程)

    然后,开发者使用这个授权码和App Key/Secret向新浪服务器换取Access Token和Refresh Token。 3. **获取用户信息**:有了Access Token,开发者可以请求用户的基本信息,如用户名、头像等,这些信息可以存储在本地...

    校园生活综合服务平台小程序的设计与实现.docx

    - **后端服务**:搭建稳定高效的服务器,并选择合适的数据存储方案。 #### 4. 安全性考虑 - **数据加密**:对敏感信息进行加密处理。 - **权限管理**:设置合理的用户权限,保护个人信息安全。 ### 知识点三:关键...

    freelec-spring-boot2-webservice

    我们将了解Spring Security的基本配置、OAuth2认证流程,以及JWT(Json Web Token)的使用,从而确保Web服务的安全性。 此外,课程还会涉及Spring Boot 2的微服务架构。我们将探讨如何使用Spring Cloud相关组件,如...

Global site tag (gtag.js) - Google Analytics