OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。OAuth不是一个认证协议,这点不要搞混。
原因
为什么需要OAuth2.0?
资源拥有者(RO)在资源服务器(RS)上存了一些照片,RO想通过客户应用打印这些照片。想访问RS上的照片,必须有用户授权才可以,传统方法是RO将自己在RS上的账号、密码提供给客户应用,然后客户应用就可以访问RS上的资源了。
但这样会有很多问题:
- 客户应用为了后续的服务,会保存用户的密码,这样很不安全。
- 资源服务器不得不部署密码登录,而我们知道,单纯的密码登录并不安全。
- 客户应用拥有了获取用户储存在资源服务器所有资料的权力,用户没法限制客户应用获得授权的范围和有效期。
- 用户只有修改密码,才能收回赋予客户应用的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。
- 只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。
OAuth2.0就可以解决这个问题。
设计
OAuth2.0能够基于令牌Token的授权,在无需暴露用户密码的情况下,使应用能够获取对用户数据的有限访问权限。
OAuth2.0主要是增加了一层授权服务器(AS),客户应用最终从授权服务器获取Token,然后使用Token获取资源服务器上的资源。
这样做好处有:
- 更安全,客户端不接触用户密码
- 针对Token可以设置寿命、访问权限
- 资源服务器和授权服务器进行解耦(理论上授权服务器和资源服务器来自同一方)
授权类型
OAuth2.0有四种授权类型。
授权码模式
授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户应用的后台服务器,与资源服务器的认证服务器进行互动。
交互图为:
假设用户想通过浏览器,使用云打印功能,打印资源服务器里的照片。用户通过浏览器在云打印应用上发起打印请求,云打印发现自己没有权限访问,返回302让用户先授权,该请求最终转发到授权服务器上,授权服务器会要求用户输入账号密码,用户输入完成后,给客户应用授予限定权限。授权服务器生成的code会根据最初请求中提供的redirect\_uri到云打印应用,这样客户应用就能获取到code。云打印应用使用code去授权服务器获取token,获得后用便可使用该token去资源服务器获取指定资源。
简化模式
简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
简化模式和授权码模式相比,不再使用授权码,User-Agent(浏览器)也能知道Token值,增加了风险。
密码模式
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
客户端模式
客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。这种模式一般用于内部服务器之间通信。
选择
上面讲了OAuth2.0的四种模式,对于不同的客户应用选择哪种模式,可以参考如下方案:
总结
OAuth已经是实际上的标准,另外也有很多框架可以支持OAuth2.0,大家如果有兴趣,可以动手实现一下。
资料
- OAuth 2.0 的四种方式
- 一张图搞定OAuth2.0
- 理解OAuth 2.0
- 认证 & 授权 1. OAuth2授权
最后
大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)
我的个人博客为:https://shidawuhen.github.io/