彻底弄懂SSO 和 OAuth2.0关系
两者的区别
SSO:单点登录。SSO 用于在一处系统中登录, 切换到其他系统时,不必再次输入用户名密码。
OAuth2.0:开放授权。 OAuth 2.0 授权框架允许第三方应用程序通过协调资源所有者和 HTTP 服务之间的审批交互,或允许第三方应用程序自己获得访问权限,从而获得对 HTTP 服务的有限访问。也就是授权别人(client)访问我们的资源。(官方定义)。 例如:使用微信扫码登陆一些第三方平台。
区别:SSO 和 OAuth2.0 在应用场景上的区别在于,SSO 是为了解决一个用户在鉴权服务器登陆过一次以后,可以在任何应用(通常是一个厂家的各个系统)中畅通无阻。OAuth2.0 解决的是通过令牌(token)而不是密码获取某个系统的操作权限(不同厂家之间的账号共享)
SSO(CAS)
SSO 实现的最关键是,在传统的多应用切换中,面临着 cookie 跨域和 session 共享的问题,解决这两个问题是实现 SSO(CAS)的关键。
下面介绍了一种单点登录的方式 CAS(中央认证服务 Central Authentication Service)
CAS 主要特征
- CAS 是对用户的账号和密码进行保存,同时也记录着用户与资源关系(是否可以访问资源)。
- 各个业务系统获得的信息是,这个用户能不能访问我的资源。资源都在各个业务那边。
- 用户登陆成功后会获得 Ticket,CAS 给业务系统一个 Ticket,业务系统是不能确定这个 Ticket 是否是用户伪造的,还是真的有效,所以要拿着这个 Ticket 去 CAS 服务器再问一下,这个用户给我的 Token 是否有效,以及会询问当前用户在我系统中的权限是什么样子的
CAS 实现流程
下面是 SSO 实现的时序图
上图具体流程如下:
- 用户访问 APP1 系统,APP1 系统是需要登录的,但用户现在没有登录。
- 跳转到 CAS server,即 SSO 登录系统。SSO 系统也没有登录,弹出用户登录页。
- 用户填写用户名、密码,SSO 系统进行认证后,将登录状态写入 SSO 的 Session,浏览器(Browser)中写入 SSO 域下的 Cookie。【此处的 Cookie 可以确保不用重复登陆 SSO 系统】
- SSO 系统登录完成后会生成一个 ST(Service Ticket),然后跳转到 APP1 系统,同时将 ST 作为参数传递给 APP1 系统。
- APP1 系统拿到 ST 后,从后台向 SSO 发送请求,验证 ST 是否有效。
- 验证通过后,APP1 系统将登录状态写入 Session 并设置 APP1 域下的 Cookie。【仅仅是在 APP1 域下的 Cookie】
至此,跨域单点登录就完成了。以后我们再访问 APP1 系统时,用户状态就已经有了。接下来,我们再看看访问 APP2 系统时的流程。 - 用户访问 APP2 系统,app2 系统没有登录,跳转到 SSO。
- 由于 SSO 已经登录了,不需要重新登录认证。【在 APP1 登陆成功后写入的 Cookie】
- SSO 生成 ST,浏览器跳转到 APP2 系统,并将 ST 作为参数传递给 APP2。
- APP2 拿到 ST,后台访问 SSO,验证 ST 是否有效。
- 验证成功后,app2 将登录状态写入 Session,并在 app2 域下写入 Cookie。
这样,APP2 系统不需要走登录流程,就已经是登录了。SSO,APP1 和 APP2 在不同的域下,它们之间的 Session 不应该是的共享的,这样可以更加保证用户信息安全。
OAuth2
OAuth 2.0 授权框架支持第三方支持访问有限的 HTTP 服务,通过在资源所有者和 HTTP 服务之间进行一个批准交互来代表资源者去访问这些资源,或者通过允许第三方应用程序以自己的名义获取访问权限。【概念比较晦涩】
例如:微信公众平台开发登录,在微信公众平台开发过程中当我们访问某个页面,页面可能弹出一个提示框,第三方应用需要获取我们的个人信息问是否被允许,点确认其实就是授权第三方应用获取我们在微信公众平台的个人信息。这里微信网页授权就是使用的 OAuth2.0。
对应资源解释:
- 资源所有者(Resource Owner):很多时候就是我们普通人(但不限于普通人,如某些应用程序也会创建资源),拥有资源的所有权。
- 资源服务器(Resource Server):保存着受保护的用户资源。(微信个人信息服务器)
- 应用程序(Client):准备访问用户资源的应用程序,其可能是一个 web 应用,或是一个后端 web 服务应用,或是一个移动端应用,也或是一个桌面可执行程序。(第三方应用)
- 授权服务器(Authorization Server):授权服务器,在获取用户的同意授权后,颁发访问令牌给应用程序,以便其获取用户资源。(微信授权服务器)
下面给大家介绍一下关于 OAuth 2.0 实现的 4 种方式。 四种授权模式时序图如下:
下面给大家详细介绍一下四种授权模式的详细过程。
授权码模式
让我们看看在增加授权服务器之后,OAuth 2.0 的一个基本授权流程。
如图上图所示,授权流程场景可以描述为如下几个步骤。(拿微信授权来讲)
- 用户在第三方应用程序中,应用程序尝试获取用户保存在 微信资源服务器上 的信息,比如用户的身份信息和头像,应用程序首先让重定向用户到授权服务器,告知申请资源的读权限,并提供自己的 client id。
- 到授权服务器,用户输入用户名和密码,服务器对其认证成功后,提示用户即将要颁发一个读权限给应用程序,在用户确认后,授权服务器颁发一个授权码(authorization code)并重定向用户回到应用程序。
- 应用程序获取到授权码之后,使用这个授权码和自己的 Client id/Secret 向认证服务器 申请访问令牌/刷新令牌(access token/refresh token)。授权服务器对这些信息进行校验,如果一切 OK,则颁发给应用程序。
- 应用程序在拿到访问令牌之后,向资源服务器申请用户的资源信息。
- 资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起 OK,则返回应用程序所需要的资源信息。
这个授权流程在 OAuth 2 中被称为授权码模式(authorization code grant),其命名的原因是,应用程序使用授权码来向授权服务器申请访问令牌/刷新令牌。
在整个过程中应用程序没有接触到用户的密码。
授权码和令牌都是一个唯一标识的值,其各个意义为。
- 授权码:即用户的委派书,代表着用户的受限权限,有时效性
- 访问令牌:用于应用程序每次向资源服务器访问时提供,有时效性,如果安全性比较高的话,则每个访问令牌可以被设置为只用一次,或者对令牌设置一个有效期,在有效期可以反复使用。
- 刷新令牌:用于应用程序向授权服务器申请新的访问令牌,在访问令牌失效或过期的时候,重新获取新的访问令牌。
注意的是,访问令牌对于应用程序来说是透明的,应用程序无需关注访问令牌所带的任何信息,只需在访问资源服务器时带上它。但是资源服务器需要知道访问令牌的组成和加密方式,资源服务器需要解析或解密这个访问令牌,查看并校验里面的信息。
授权服务器和访问令牌,前者为授权的颁发,后者为授权的载体,两者实现了动态按需地代理权限分发,这也是 OAuth 2.0 解决方案在授权上所带来的创新变化。
授权模式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
简化模式
这种场景经常运用应用程序没有服务端的情况。 应用程序运行在客户端,一个最大的变化就是其变成了公开应用程序(Public Client),应用程序的运行完全暴露在用户的控制之中。在这种场景下,应用程序是无法隐藏自己的一些敏感数据,比如 client secret 和授权码,在这个方式下,再向授权服务器获取授权码是多此一举。
为此 OAuth 2.0 提供简化模式,授权服务器在校验好用户信息后,直接颁发给应用程序访问资源服务器的访问令牌。换句话说,应用程序在获取访问令牌时无需提供授权码和 client secret。
这个授权模式被称为简化模式,其命名的原因主要是由于跳过获取授权码这一中间过程,无需授权码而可以直接获取访问令牌。
整个授权流程如下,
- 用户在应用程序中,应用程序尝试获取用户保存在资源服务器上的信息,比如用户的身份信息和头像,应用程序首先让用户重定向到授权服务器,告知申请资源的读权限,并提供自己的 client id。在重定向的过程中,应用程序指定使用 Implicit Grant 授权方式。
- 在授权服务器,用户输入用户名和密码,服务器对其认证成功后,提示用户即将要颁发一个读权限给应用程序,在用户确认后,授权服务器直接颁发一个访问令牌并重定向用户回到应用程序。
- 应用程序在拿到访问令牌之后,向资源服务器申请用户的资源信息
- 资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起 OK,则返回应用程序所需要的资源信息。
这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。
应用授信
这种授信模式特点是:应用程序角色本身就是资源所有者 (应用程序和资源服务器之间是完全可信的)
这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。
- 应用程序尝试获取在资源服务器上的信息,应用程序直接向授权服务器申请访问令牌,告知申请资源的读权限,并提供自己的授信凭证(client id/secret)。在申请请求中,应用程序指定使用 client credentials 授权方式。在授权服务器,服务器对其 client credentials 校验成功后,授权服务器直接颁发一个访问令牌给应用程序。
- 应用程序在拿到访问令牌之后,向资源服务器申请用户的资源信息。
- 资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起 OK,则返回应用程序所需要的资源信息。
这个授权流程被称为应用授信模式,其命名原因是由于应用程序是通过自己的授信凭证(client id/secret)直接向授权服务器申请访问令牌。这种模式一般用在可信的应用程序。
和简化模式一样,授权服务器无需颁发刷新令牌给应用程序,原因很简单,应用程序想要的话,直接再调用授权服务器一次即可。
用户授信模式
在基本的授权码模式中,用户需要跳转到授权服务器上,使用用户名和密码登录后拿到授权码,然后把授权码交给应用程序,然后再去申请访问令牌。但有些时候,能否省去这个来回的跳转过程,把用户名和密码直接交给应用程序,让应用程序去申请访问令牌。
这个就是用户授信模式的应用场景,这个场景其实回到了本文中最先提到的授权使用场景,应用程序有接触到用户的用户名和密码,因此,应用程序必须是完全可信的。
用户授信模式流程如下:
- 用户在应用程序中,应用程序首先让用户到登录页面输入用户名和密码。
- 应用程序拿到资源所有者的用户名和密码,加上自己的 client id/secret 一同向认证服务器申请访问令牌/刷新令牌。授权服务器对这些信息进行校验,如果通过,则颁发给应用程序访问令牌/刷新令牌。
- 应用程序在拿到访问令牌/刷新令牌之后,向资源服务器申请用户的资源信息。
- 资源服务器在获取到访问令牌后,对令牌进行解析(如果令牌已加密,则需要进行使用相应算法进行解密)并校验,并向授权服务器校验其合法性,如果一起 OK,则返回应用程序所需要的资源信息。
这个授权流程被称为用户授信模式,其命名原因是由于应用程序是通过用户的授信凭证(比如:用户名和密码)向授权服务器申请访问令牌。
当应用程序换取到访问令牌之后,从安全的角度考虑,应用程序应该立即删除用户的授信凭证,不再保留。这也是 OAuth 2.0 所建议的安全规范,应用程序不应该通过用户的用户名和密码,而是应该都通过访问令牌去访问资源。
四种授权模式的联系和区别
OAuth 2.0 的四种授权模式,有一定的联系,也有区别。前文也对这些联系和区别做了一些描述,这里做下小结。
无论哪种授权模式,都是以获取访问令牌为目的,访问令牌是各个授权模式交互的最终结果。
我们先比较下各个模式获取访问令牌的手段,
- 授权码模式:授权码+应用的授信凭据
- 简化模式:应用 client id + 用户的授信凭据
- 应用授信模式:应用的授信凭据
- 用户授信模式:应用的授信凭据+用户的授信凭据
上面说的,应用的授信凭据是指 client id 和 secret,用户的授信凭据则一般是用户名和密码。
这四种授权模式中,授权码模式是基本的授权模式,
- 授权码模式:基本授权模式,它需要有四个角色同时在场才能完成授权:资源所有者、应用程序、授权服务器、资源服务器。
其它三种模式可以在其基本的授权码模式上演绎出来, - 简化模式:开放应用程序,应用程序运行在公开开放的环境。 即:无需应用程序的认证。
- 应用授信模式:应用程序即为资源所有者,或资源所有者不参与授权交互。 即:无资源所有者的认证。
- 用户授信模式:无授权码的颁发过程,直接通过用户名和密码换取授权。
下面是具体的演绎过程:
如何选择合适 OAuth 2.0 授权方式
面对四种授权方式,如何为自己的应用场景选择一种授权模式。简单的话,可以根据下面的流程图来进行参考选择。
相关链接: