集成基于OAuth协议的单点登陆
在之前的一篇文章中,我们已经介绍了如何为一个应用添加对CAS协议的支持,进而使得我们的应用可以与所有基于CAS协议的单点登陆服务通讯。但是现在的单点登陆服务实际上并不全是通过实现CAS协议来完成的。例如Google就使用OAuth协议来管理它的帐户。
相较于CAS协议,OAuth协议不仅仅可以完成对用户凭证的验证,更可以提供权限管理的功能。在这些权限管理功能的支持下,一个应用甚至可以访问其它使用相同OAuth服务的应用的数据,从而完成应用间的交互。
OAuth集成示例
现在我们就来看一个通过OAuth协议来访问其它应用资源的示例。
相信您或者您的许多朋友都已经在微信中关联了LinkedIn帐号,从而可以显示相应LinkedIn帐号的一些信息。要做到这一点,我们首先需要在微信的“设置”-> “通用”-> “功能”-> “LinkedIn”下找到关联LinkedIn帐号的功能:

在点击了关联帐号以后,我们将跳转到LinkedIn。此时LinkedIn会要求我们输入LinkedIn帐号的用户名和密码,进而允许微信访问LinkedIn帐号的部分信息:

再跳转回到微信的时候,我们就可以看到微信已经能够访问相应的LinkedIn帐号的相关信息了:

关联流程简介
那微信和LinkedIn之间的关联是如何建立的呢?答案就是OAuth协议。在本节中,我们将对OAuth协议的运行流程进行简单地介绍。
注:我个人所做的工作是为Web应用添加OAuth集成。为该类型应用集成OAuth协议从流程上来说相对简单,反过来却无法较为全面地展现OAuth协议的整体运行流程。因此在本节中我们假设手机中运行的微信是一个“confidential clients”,并可以“capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection)”(RFC6749 – Section 4.1)。
实际上,在用户点击微信中的“关联帐号”这个按钮的时候,微信可能就开始启动手机浏览器并转向下面的地址:
https://{linkedin_oauth_url}/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx
该URL中包含了五个较为重要的URL参数:
- client_id。表示微信在LinkedIn中所对应的应用ID
- redirect_uri。表示在得到了用户授权后所需要返回到的地址
- scope。表示当前应用所申请的权限
- response_type。表示当前应用所请求的Authorization Grant的类型
- state。表示当前应用的状态
一旦成功转向了该URL,那么手机浏览器将显示LinkedIn的用户登录并赋予权限的页面。如果用户成功登陆并允许微信访问这些信息,那么我们的浏览器将会被重定向到redirect_uri所标示的地址。再该地址中还会通过URL参数code来记录所得到的Authorization Grant:
https://{redirect_uri}?code=AUTHORIZATION_CODE
在浏览器重定向到{redirect_uri}之后,微信就知道用户已经给与了它访问当前用户的LinkedIn信息的权限,并通过URL参数code来分析出刚从OAuth服务中得到的AUTHORIZATION_CODE。接下来,微信就会通过刚刚得到的AUTHORIZATION_CODE尝试向下面的地址发送请求,以请求访问资源所需要的令牌:
https://{linkedin_oauth_url}/token?client_id=CLIENT_ID&code=AUTHORIZATION_CODE&grant_type=authorization_code&redirect_uri=CALLBACK_URL
上面的请求中包含了四个URL参数:
- client_id:表示微信在LinkedIn中所对应的应用ID
- code:用来标示我们刚刚从服务端所得到的Authorization Grant
- grant_type:用来标示Authorization Grant的类型
- redirect_uri:用来标示成功获得令牌的情况下所需要返回的URL
在应用成功地得到了访问资源的令牌之后,LinkedIn将返回一个包含了资源访问令牌的响应。同时浏览器将被重定向到redirect_uri所标示的位置。
接下来,应用就可以通过刚刚获得的资源访问令牌来访问目标资源了。
总的来说,微信(Wechat)通过OAuth协议获得用户帐号信息的流程如下所示:

OAuth协议集成
在经过前面的示例讲解之后,相信读者们已经大概了解了OAuth协议的大致运行流程了。那么我们现在就可以开始考虑集成OAuth协议了?是的。但是在这之前,我们首先要在OAuth服务上注册应用。
不幸的是,LinkedIn似乎没有对普通用户公开应用注册的接口。因此我们将以Digital Ocean来演示如何在一个OAuth服务上注册一个应用。
首先,请在浏览器的地址栏中键入https://www.digitalocean.com/以来到Digital Ocean的主页面,并注册/登录。接下来,在登入的界面中点击上方的“API”,以进入应用管理页面:

在该页面中,我们需要点击“Register New Application”来进入应用注册页面。而在该注册页面中,我们需要提供应用的一系列信息。这些信息包括:
- 应用的名称
- 应用的地址
- 应用的重定向URL,即获得了Authorization Code或资源访问令牌后应用所需要重定向到的默认地址
注册完毕以后,我们就会得到一个应用的ID以及相应的应用凭证。这一对信息用来在OAuth协议运行过程中证明应用的合法性。
现在我们就可以开始尝试在应用中集成对OAuth协议的支持了。在OAuth协议的第一步,我们需要向OAuth服务提供者发送权限请求,以要求用户赋予访问信息的权限。就像流程简介中所讲的那样,该请求的目标URL常常包含五个参数:
- client_id。表示应用在OAuth服务中注册时所得到的应用ID
- redirect_uri。表示在应用得到了用户授权后所需要返回到的地址
- scope。表示当前应用所申请的权限
- response_type。表示当前应用所请求的Authorization Grant的类型
- state。表示应用的当前状态。通过该参数,应用可以恢复至特定状态
这里的五个参数都非常容易理解,但它们仍然有需要注意的地方。首先要说明的一点就是redirect_uri。它实际上是一个可选参数。在没有标明该参数的情况下,OAuth服务所返回的重定向响应就将返回到我们刚刚在应用注册时所指定的URL。只是在一般情况下,我们都会在发送权限请求的时候显式地标明该参数。这在应用使用了负载平衡,分区域部署等解决方案的情况下可以更好地对应用的性能,服务的负载等众多方面进行控制。
接下来要说的URL参数就是scope。很不幸地,在OAuth协议中并没有规定该参数的取值范围。也就是说,不同的OAuth服务所接受的scope参数的取值范围可能并不相同。这听起来可能令人有些沮丧。但是如果OAuth协议集成框架实现得比较好的情况下,该URL参数完全可以作为框架的一个可配置的参数暴露给框架的使用者。
最后要说的就是response_type参数。OAuth协议是一个可以在多种场景下使用的协议,如Web应用,手机应用等。它们在不同的应用场景下面对的风险和需求都各不相同,从而产生了不同的获得资源访问令牌的方法。因此您需要根据应用的实际情况选择合适的参数。而在这里,我们选择使用code,即Authorization Code Grant。因为其流程最为复杂,而且还支持资源访问令牌的刷新。
在向OAuth服务发送了请求之后,如果浏览器能够正确地显示OAuth服务要求用户赋予权限的页面,那就表示对OAuth服务的第一步集成已经成功了。
在正确地输入了用户名和密码,并同意应用的访问请求后,应用将接收到一个重定向响应。在接收到该响应之后,应用将记录URL参数code所标明的权限请求所得到的令牌,并使用state参数来恢复应用的状态。
如果成功地得到权限令牌并恢复了应用状态,我们就需要开始下一步工作:通过权限令牌来得到资源访问令牌。在这一步中,我们需要像OAuth服务器发送如下形式的请求:
https://{linkedin_oauth_url}/token?client_id=CLIENT_ID&code=AUTHORIZATION_CODE&grant_type=authorization_code&redirect_uri=CALLBACK_URL
该请求中常常包含四个URL参数:
- client_id:表示应用在OAuth服务中所对应的应用ID
- code:用来标示我们刚刚从服务端所得到的权限令牌
- grant_type:用来标示Authorization Grant的类型
- redirect_uri:用来标示成功获得资源访问令牌的情况下所需要返回的URL
如果请求成功地得到了服务的响应,那么我们就需要从响应中分析得到资源访问令牌access_token以及其它的一系列信息:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "code",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter": "xxx"
}
在成功地从响应中解析出了资源访问令牌以后,我们就可以尝试着向资源服务器发送资源访问请求了。在该请求中,我们只需要将资源访问令牌作为请求的Authorization头即可。如果资源能够成功返回,那么表示我们对OAuth协议的集成已经基本成功了。
Refresh Token
当然,工作还没有完全结束。在从OAuth服务器所得到的响应中还有一个较为重要的信息:refresh_token。它用来从OAuth服务那里再次获得一个资源访问令牌。这在原有的资源访问令牌过期的情况下非常有用。
在需要通过refresh token更新资源访问令牌的时候,我们需要向OAuth服务再次发送一个获取资源访问令牌的请求。只是在该请求中,我们需要将URL参数grant_type设置为“refresh_token”,并通过URL参数refresh_token来标明之前得到的refresh_token。如果OAuth服务能够返回一个正确的响应并且能够通过该响应中包含的新的资源访问令牌访问资源服务器上的资源,那么就表示我们已经完成了对refresh token的支持。
Reference
OAuth协议:http://tools.ietf.org/html/rfc6749
转载请注明原文地址并标明转载:http://www.cnblogs.com/loveis715/p/4491456.html
商业转载请事先与我联系:silverfox715@sina.com
注:
- 本文在讲解OAuth流程时所列出的各个URL只用来作为讲解使用,而不作为任何考证依据。一切URL格式都应以相应版本协议中所定义的URL格式为准
- 本文在介绍微信与LinkedIn关联的图片来自于百度经验
集成基于OAuth协议的单点登陆的更多相关文章
- 集成基于CAS协议的单点登陆
相信大家对单点登陆(SSO,Single Sign On)这个名词并不感到陌生吧?简单地说,单点登陆允许多个应用使用同一个登陆服务.一旦一个用户登陆了一个支持单点登陆的应用,那么在进入其它使用同一单点 ...
- OAuth协议——PHP第三方登陆协议
慕课网Badguy老师的良心课程! 总会有那种什么都不想干的时候,但现在的日子又不这么允许个人的放纵,我一般就只有这几个选择:看课程视频,看书,看小说..好像还是有可以做的事情.其中,看课程视频有点无 ...
- IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理
1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以“人”为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是整个IM系统都是以长 ...
- 基于 OAuth 安全协议的 Java 应用编程1
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-oauth/index.html 參考博客:http://www.cnblogs.com/wan ...
- 基于 OAuth 安全协议的 Java 应用编程
OAuth 简介 OAuth 是由 Blaine Cook.Chris Messina.Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全. ...
- Spring Security 解析(六) —— 基于JWT的单点登陆(SSO)开发及原理解析
Spring Security 解析(六) -- 基于JWT的单点登陆(SSO)开发及原理解析 在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把 ...
- Spring Security 集成 CAS(基于HTTP协议版本)
Spring Security 集成 CAS(基于HTTP协议版本) 近段时间一直研究Spring Security 集成 CAS,网上资料相关资料也很多,不过大都是基于Https的安全认证;使用ht ...
- 对OAuth协议的认识
一. OAuth是什么 OAuth 是Open Authorization的简写.OAuth 协议为用户资源的授权提供了一个安全的.开放而又简易的标准. 通俗地说,就是当我们想把自己系统的某些功能暴露 ...
- 谈谈基于OAuth 2.0的第三方认证 [上篇]
对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成.具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确认其真实身份.但是这种由Web应用全权负 ...
随机推荐
- 富文本编辑器Simditor的简易使用
最近打算自己做一个博客系统,并不打算使用帝国cms或者wordpress之类的做后台管理!自己处于学习阶段也就想把从前台到后台一起谢了.好了,废话不多说了,先来看看富文本编辑器SimDitor,这里是 ...
- Android消息传递之基于RxJava实现一个EventBus - RxBus
前言: 上篇文章学习了Android事件总线管理开源框架EventBus,EventBus的出现大大降低了开发成本以及开发难度,今天我们就利用目前大红大紫的RxJava来实现一下类似EventBus事 ...
- JS魔法堂:不完全国际化&本地化手册 之 理論篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- C#项目中文件的具体含义
1.Bin 目录 用来存放编译的结果,bin是二进制binary的英文缩写,因为最初C编译的程序文件都是二进制文件,它有Debug和Release两个版本,分别对应的文件夹为bin/Debug和bin ...
- Java中用得比较顺手的事件监听
第一次听说监听是三年前,做一个webGIS的项目,当时对Listener的印象就是个"监视器",监视着界面的一举一动,一有动静就触发对应的响应. 一.概述 通过对界面的某一或某些操 ...
- Take into Action!
很久没有认真地写文字了. 刚毕业一两年断断续续在csdn上写过一些当时的工作记录,然后没有坚持下去.有时候是觉得自己不牛,记录的东西旁人看起来也许不值一提:有时候觉得结婚生娃了,然后时间不够用(确实是 ...
- Node.js入门
开始之前,安利一本正在看的书<站在两个世界的边缘>,作者程浩,上帝丢给他太多理想,却忘了给他完成理想的时间.OK,有兴趣的可以看一看. node.js如标题一样,我也是刚开始接触,大家一起 ...
- Atitit.attilax软件研发与项目管理之道
Atitit.attilax软件研发与项目管理之道 1. 前言4 2. 鸣谢4 3. Genesis 创世记4 4. 软件发展史4 5. 箴言4 6. 使徒行传 4 7. attilax书 4 8. ...
- 关于sqlmap的使用
好记性不如烂笔头,记录一下. 带cookie的注入 python sqlmap.py -u "http://www.xxx.com?id=1" --cookie="coo ...
- 用lucene替代mysql读库的尝试
采用lucene对mysql中的表建索引,并替代全文检索操作. 备注:代码临时梳理很粗糙,后续修改. import java.io.File; import java.io.IOException; ...