为什么需要OAuth2.0?
编码永远都是为了解决生产中的问题,想要理解为什么需要OAuth2,当然要从实际生活出发。
举个例子:小区的业主点了一份外卖,但是小区的门禁系统不给外卖人员进入,此时想要外卖员进入只能业主下来开门或者告知门禁的密码。
密码告知外卖员岂不是每次都能凭密码进入小区了,这明显造成了安全隐患。
那么有没有一种方案:既能不泄露密码,也能让外卖小哥进入呢?
于是此时就想到了一个授权机制,分为以下几个步骤:
- 门禁系统中新增一个授权按钮,外卖小哥只需要点击授权按钮呼叫对应业主
- 业主收到小哥的呼叫,知道小哥正在要求授权,于是做出了应答授权
- 此时门禁系统弹出一个密码(类似于access_token),有效期30分钟,在30分钟内,小哥可以凭借这个密码进入小区。
- 小哥输入密码进入小区
另外这个授权的密码不仅可以通过门禁,还可以通过楼下的门禁,这就非常类似于网关和微服务了。
令牌和密码的区别?
上述例子中令牌和密码的作用是一样的,都可以进入小区,但是存在以下几点差异:
- 时效不同:令牌一般都是存在过期时间的,比如30分钟后失效,这个是无法修改的,除非重新申请授权;而密码一般都是永久的,除非主人去修改
- 权限不同:令牌的权限是有限的,比如上述例子中,小哥获取了令牌,能够打开小区的门禁、业主所在的楼下门禁,但是可能无法打开其它幢的门禁;
- 令牌可以撤销:业主可以撤销这个令牌的授权,一旦撤销了,这个令牌也就失效了,无法使用;但是密码一般不允许撤销。
什么是OAuth2?
OAuth 是一个开放标准,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),而在这个过程中无需将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌(token),而不是用户名和密码来访问他们存放在特定服务提供者的数据。
采用令牌(token)的方式可以让用户灵活的对第三方应用授权或者收回权限。
OAuth2 是 OAuth 协议的下一版本,但不向下兼容 OAuth 1.0。
传统的 Web 开发登录认证一般都是基于 session 的,但是在前后端分离的架构中继续使用 session 就会有许多不便,因为移动端(Android、iOS、微信小程序等)要么不支持 cookie(微信小程序),要么使用非常不便,对于这些问题,使用 OAuth2 认证都能解决。
对于大家而言,我们在互联网应用中最常见的 OAuth2 应该就是各种第三方登录了,例如 QQ 授权登录、微信授权登录、微博授权登录、GitHub 授权登录等等。
OAuth2.0的四种模式?
OAuth2.0协议一共支持 4 种不同的授权模式:
- 授权码模式:常见的第三方平台登录功能基本都是使用这种模式。
- 简化模式:简化模式是不需要客户端服务器参与,直接在浏览器中向授权服务器申请令牌(token),一般如果网站是纯静态页面则可以采用这种方式。
- 密码模式:密码模式是用户把用户名密码直接告诉客户端,客户端使用说这些信息向授权服务器申请令牌(token)。这需要用户对客户端高度信任,例如客户端应用和服务提供商就是同一家公司,自己做前后端分离登录就可以采用这种模式。
- 客户端模式:客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权,严格来说,客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。
1、授权码模式
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
令牌获取的流程如下:
上图中涉及到两个角色,分别是客户端、认证中心,客户端负责拿令牌,认证中心负责发放令牌。
但是不是所有客户端都有权限请求令牌的,需要事先在认证中心申请,比如微信并不是所有网站都能直接接入,而是要去微信后台开通这个权限。
至少要提前向认证中心申请的几个参数如下:
client_id:客户端唯一id,认证中心颁发的唯一标识
client_secret:客户端的秘钥,相当于密码
scope:客户端的权限
redirect_uri:授权码模式使用的跳转uri,需要事先告知认证中心。
1、请求授权码
客户端需要向认证中心拿到授权码,比如第三方登录使用微信,扫一扫登录那一步就是向微信的认证中心获取授权码。
请求的url如下:
/oauth/authorize?client_id=&response_type=code&scope=&redirect_uri=
上述这个url中携带的几个参数如下:
client_id:客户端的id,这个由认证中心分配,并不是所有的客户端都能随意接入认证中心
response_type:固定值为code,表示要求返回授权码。
scope:表示要求的授权范围,客户端的权限
redirect_uri:跳转的uri,认证中心同意或者拒绝授权跳转的地址,如果同意会在uri后面携带一个
code=xxx
,这就是授权码
2、返回授权码
第1步请求之后,认证中心会要求登录、是否同意授权,用户同意授权之后直接跳转到redirect_uri
(这个需要事先在认证中心申请配置),授权码会携带在这个地址后面,如下:
http://xxxx?code=NMoj5y
3、请求令牌
客户端拿到授权码之后,直接携带授权码发送请求给认证中心获取令牌,请求的url如下:
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101
}
access_token则是颁发的令牌,refresh_token是刷新令牌,一旦令牌失效则携带这个令牌进行刷新。
2.简化模式
3.密码模式
密码模式也很简单,直接通过用户名、密码获取令牌,流程如下:
入门案例
创建认证服务器
创建资源服务器