在之前的一篇文章中,我们已经介绍了如何为一个应用添加对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. 前端框架 EasyUI (0) 重新温习(序言)

    几年前,参与过一个项目.那算是一个小型的信息管理系统,BS 结构的,前端用的是基于 jQuery 的 EasyUI 框架. 我进 Team 的时候,项目已经进入开发阶段半个多月了.听说整个项目的框架是 ...

  2. java EE设计模式简介

    1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...

  3. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

  4. LINQ to SQL Select查询

    1. 查询所有字段 using (NorthwindEntities context = new NorthwindEntities()) { var order = from n in contex ...

  5. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  6. BZOJ 2119: 股市的预测 [后缀数组 ST表]

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 331  Solved: 153[Submit][Status][Discuss ...

  7. VS2010 release编译下进行调试,“当前不会命中任何断点,还没有为文档加载”问题解决方案

    在release模式下调试程序,经常出现"当前不会命中任何断点,还没有为文档加载"的问题,可尝试以下方法: 1. 属性 → 配置属性 → C/C++ → 常规 → 调试信息格式:选 ...

  8. 开源发布:VS代码段快捷方式及可视化调试快速部署工具

    前言: 很久前,我发过两篇文章,分别介绍自定义代码版和可视化调试: 1:Visual Studio 小技巧:自定义代码片断 2:自定义可视化调试工具(Microsoft.VisualStudio.De ...

  9. linux下mono播放PCM音频

         测试环境: Ubuntu 14 MonoDevelop CodeBlocks 1.建立一个共享库(shared library) 这里用到了linux下的音频播放库,alsa-lib. al ...

  10. ES6+ 现在就用系列(二):let 命令

    系列目录 ES6+ 现在就用系列(一):为什么使用ES6+ ES6+ 现在就用系列(二):let 命令 ES6+ 现在就用系列(三):const 命令 ES6+ 现在就用系列(四):箭头函数 => ...