最近项目上接触ouath2.0比较多,很多大厂都用来做单点登入,写篇文章分享一下,一起探讨学习。
什么是Oauth2.0?
oauth协议为用户资源的授权提供了一个安全的、开放而又建议的标准。oauth的授权不会使第三方触及到用户的账号信息(如用户名与密码),及第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此oauth是安全的。
oauth是Open Authorization的简写。
简单来说,oauth是一套授权协议,常见的应用场景是用于联合登入服务,比如登入某个平台后,可以再授权单点登入其它子平台。
实现流程(授权码模式)
上图为一次oauth2.0的登入逻辑。可供参考
四种模式
1、授权码
授权码模式(authorization code)是功能最完整、流程最严密的授权模式,也是推荐的模式。
用户在授权端点登入后,将授权码(code)拼接在url上,用户通过重定向URL返回到web应用(客户端)时,应用程序将从URL获得授权代码,并使用它来请求访问令牌。获取访问令牌后,才能到用户信息端点获取用户详细信息。
访问令牌请求将包含以下参数:
grant_type :该grant_type参数必须设置为“ authorization_code”。
code :此参数是客户端先前从授权服务器接收到的授权代码。
client_id :如果客户端通过HTTP Basic Auth或其他方法进行身份验证,则不需要此参数。否则,此参数是必需的。主要用于对客户端进行身份验证。
服务器检查授权码是否有效,并且尚未过期。然后,服务必须验证请求中提供的授权代码是否已发给所标识的客户端。最后,服务必须确保存在的重定向URI参数与用于请求授权代码的重定向URI匹配。
如果一切都检查完了,该服务可以生成一个访问令牌并做出响应。
2、客户凭证
客户端使用“客户端证书”授予类型来获取访问令牌。然后根据令牌获取用户信息用于登入。没有携带code重定向的过程。
必须的请求参数:
grant_type :该grant_type参数必须设置为client_credentials。
客户端身份验证:客户端需要对此请求进行身份验证。通常,该服务将允许其他请求参数client_id和client_secret,或者在HTTP Basic auth标头中接受客户端ID和密码。
POST /token HTTP/1.1
Host: authorization-server.com
grant_type=client_credentials
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx
3、设备代码
设备代码授权类型由设备流程中无浏览器或输入受限的设备使用,以将先前获得的设备代码交换为访问令牌。为了方便理解,画了以下流程图:
常见的应用是一些无人售货机、ktv等,当用户需要登入时,试想一下,通过简单的键盘输入复杂的用户名和密码、丑陋页面用来进行登入操作,显然用户体验大打折扣。这时候,如果只需要用户通过app来完成登入,那样的体验会更好。
4、刷新令牌
客户端使用“刷新令牌”授予类型在访问令牌过期时将刷新令牌交换为访问令牌。这允许客户端继续拥有有效的访问令牌,而无需与用户进行进一步的交互。
安全注意事项
1、防止重放攻击
简单来说,就是浏览器端的授权码code被劫持。如果code被恶意获取,则其它人有可能可以使用这个code进行登入,面临安全问题。
一种有效的策略是,每个code只能使用一次,即使被恶意获取了,也是一个无效的code。为了实现这个过程,官方提供了两种有效的思路:
a、如果授权码存储在数据库中,这很容易实现,只需要将它们简单地标记为已使用就可以了。
b、将令牌端点服务器将使用过的code存在缓存中,每次检验请求中的code时,都去缓存中检查是否已经存在;如果一个代码被多次使用,则应将其视为攻击。如果可能,服务应撤消从此授权码发出的先前的访问令牌。
2、跨站点请求伪造(CSRF)
CSRF是一种诱使受害者提交恶意请求的攻击。它继承了受害者的身份和特权,可以代表受害者执行不希望的功能。对于大多数站点,浏览器请求将自动包括与该站点相关联的任何凭据,例如用户的会话cookie,IP地址,Windows域凭据等。因此,如果用户当前已通过站点认证,则该站点将无法区分受害者发送的伪造请求和受害者发送的合法请求。
简单来说,就是用户已经通过验证并登入了web应用,然后向该站点发送恶意请求,例如更改受害者的电子邮件地址或密码,或购买某些东西。总之,CSRF攻击以状态更改请求为目标。
解决办法:ouath2.0提供了一种解决方案,在第2步重定向到授权端点时,携带一个state(一个随机数)的参数,当授权完毕再访问web应用时,需要web应用检查这个参数是否一致,不一致的话对该请求不响应。
重定向过程中参数丢失的问题
在项目中可能会遇到一个问题,由于重定向到授权端点后,再重定向会web应用时,重定向的url为授权端点用户设置的回调地址,因此会导致url上的参数丢失。针对这个问题,提出一种解决方法:
1、第二步从web应用重定向到授权端点时,先将请求中的参数存贮到session中,这些参数会在服务器上保留一段时间;
2、当用户完成授权验证,重定向再次访问web应用时,完成登入操作后,再将session中的参数取出拼到url上,再请求转发(forward)即可。
由于session还存活,因此在有效期内,用户每次访问服务器都能访问到相同的session,拿回这些信息。当然,如果两次访问的时间间隔太长、或者清除浏览器缓存,则访问不到相同的session,但是这种情况非常少见,因此这是一种可用的方法。