这篇文章源于一场面试,讲真的面试是很快发现自己不足的一种途径。
面试官提出的问题是:“介绍下OAuth2.0”。起初听到这个问题很慌,我对OAuth2.0本是一无所知,只知道它是授权机制罢了,但是我使用过JWT,于是我就吧啦吧啦说了一些JWT的知识。
现在想想真是滑稽,OAuth2.0与JWT貌似毛关系都没有,借此很痛的领悟整理下OAuth与JWT吧。
一.OAuth是什么?
OAuth的英文全称是Open Authorization,它是一种开放授权协议。
- 允许用户让第三方应用访问该用户在某一网站上存储的的资源(如:照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
- OAuth是一个关于授权(Authorization)的开放网络标准,目前的版本是2.0版。注意是Authorization(授权),而不是Authentication(认证)。用来做Authentication(认证)的标准叫openid connect。
OAuth定义了四种角色
- resource owner(资源所有者)
- resource server(资源服务器)
- client(客户端):代表资源所有者并且经过所有者授权去访问受保护的资源的应用程序
- authorization server(授权服务器):在成功验证资源所有者并获得授权后向客户端发出访问令牌
抽象的OAuth2.0流程如图所示:
- (A) 客户端向资源所有者请求其授权
- (B) 客户端收到资源所有者的授权许可,这个授权许可是一个代表资源所有者授权的凭据
- (C) 客户端向授权服务器请求访问令牌,并出示授权许可
- (D) 授权服务器对客户端身份进行认证,并校验授权许可,如果都是有效的,则发放访问令牌
- (E) 客户端向资源服务器请求受保护的资源,并出示访问令牌
- (F) 资源服务器校验访问令牌,如果令牌有效,则提供服务
OAuth2.0客户端的授权模式
授权码模式(authorization code)
功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。
简化模式(implicit grant type)
不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
密码模式(Resource Owner Password Credentials Grant)
用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
客户端模式(Client Credentials Grant)
指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
授权码模式
其中最常用的是授权码模式,我们详细讲解一下。其中最常用的是授权码模式,我们详细讲解一下。
在另外一篇文章中《OAuth2.0之授权码模式》。
JWT是什么
JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑(Compact)且自包含(Self-contained)的方式,用于在各方之间以JSON对象安全传输信息。 这些信息可以通过数字签名进行验证和信任。 可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名。
JWT的详细介绍在另一篇文章中。
OAuth2.0与JWT的比较
OAuth2.0和JWT是完全不同的两种东西,在这里我们强制比较下。
- OAuth2.0是授权认证的框架,是规范不是实现。
- JWT则是认证验证的方式方法(轻量级概念),是一种具体的Token实现框架。OAuth2.0不像JWT一样是一个严格的标准协议,因此在实施过程中更容易出错。
- OAuth2.0用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app)。
- JWT是用在前后端分离, 需要简单的对后台API进行保护时使用(前后端分离无session, 频繁传用户密码不安全)。
JWT与Session还有有的一比的
- 相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的。
- Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。 而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。
- Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。