在之前的一篇文章中,我们已经介绍了如何为一个应用添加对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

注:

  1. 本文在讲解OAuth流程时所列出的各个URL只用来作为讲解使用,而不作为任何考证依据。一切URL格式都应以相应版本协议中所定义的URL格式为准
  2. 本文在介绍微信与LinkedIn关联的图片来自于百度经验

集成基于OAuth协议的单点登陆的更多相关文章

  1. 集成基于CAS协议的单点登陆

    相信大家对单点登陆(SSO,Single Sign On)这个名词并不感到陌生吧?简单地说,单点登陆允许多个应用使用同一个登陆服务.一旦一个用户登陆了一个支持单点登陆的应用,那么在进入其它使用同一单点 ...

  2. OAuth协议——PHP第三方登陆协议

    慕课网Badguy老师的良心课程! 总会有那种什么都不想干的时候,但现在的日子又不这么允许个人的放纵,我一般就只有这几个选择:看课程视频,看书,看小说..好像还是有可以做的事情.其中,看课程视频有点无 ...

  3. IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理

    1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以“人”为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是整个IM系统都是以长 ...

  4. 基于 OAuth 安全协议的 Java 应用编程1

    原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-oauth/index.html 參考博客:http://www.cnblogs.com/wan ...

  5. 基于 OAuth 安全协议的 Java 应用编程

    OAuth 简介 OAuth 是由 Blaine Cook.Chris Messina.Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全. ...

  6. Spring Security 解析(六) —— 基于JWT的单点登陆(SSO)开发及原理解析

    Spring Security 解析(六) -- 基于JWT的单点登陆(SSO)开发及原理解析   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把 ...

  7. Spring Security 集成 CAS(基于HTTP协议版本)

    Spring Security 集成 CAS(基于HTTP协议版本) 近段时间一直研究Spring Security 集成 CAS,网上资料相关资料也很多,不过大都是基于Https的安全认证;使用ht ...

  8. 对OAuth协议的认识

    一. OAuth是什么 OAuth 是Open Authorization的简写.OAuth 协议为用户资源的授权提供了一个安全的.开放而又简易的标准. 通俗地说,就是当我们想把自己系统的某些功能暴露 ...

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

    对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成.具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确认其真实身份.但是这种由Web应用全权负 ...

随机推荐

  1. 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧

    记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...

  2. Angular企业级开发(5)-项目框架搭建

    1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...

  3. 告别被拒,如何提升iOS审核通过率(上篇)

    iOS审核一直是每款移动产品上架苹果商店时面对的一座大山,每次提审都像是一次漫长而又悲壮的旅行,经常被苹果拒之门外,无比煎熬.那么问题来了,我们有没有什么办法准确把握苹果审核准则,从而提升审核的通过率 ...

  4. 彻底理解AC多模式匹配算法

    (本文尤其适合遍览网上的讲解而仍百思不得姐的同学) 一.原理 AC自动机首先将模式组记录为Trie字典树的形式,以节点表示不同状态,边上标以字母表中的字符,表示状态的转移.根节点状态记为0状态,表示起 ...

  5. 简单粗暴地理解js原型链--js面向对象编程

    原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧, ...

  6. ABP文档 - 异常处理

    文档目录 本节内容: 简介 启用错误处理 非AJAX请求 显示异常 UserFriendlyException Error 模型 AJAX 请求 异常事件 简介 这个文档针对Asp.net Mvc和W ...

  7. JavaScript 字符串实用常操纪要

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  8. js复杂对象和简单对象的简单转化

    var course = { teacher :{ teacherId:001, teacherName:"王" }, course : { courseId : 120, cou ...

  9. 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  10. 基于SignalR实现B/S系统对windows服务运行状态的监测

    通常来讲一个BS项目肯定不止单独的一个BS应用,可能涉及到很多后台服务来支持BS的运行,特别是针对耗时较长的某些任务来说,Windows服务肯定是必不可少的,我们还需要利用B/S与windows服务进 ...