「时光不负,创作不停,本文是今年日更计划第6篇文章」
今天是元旦假期最后一天,学习一下码猿技术专栏中的OAuth2.0模块,记录一下。
妹子始终没搞懂OAuth2.0,今天整合Spring Cloud Security 一次说明白!
为什么需要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 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。
3、密码模式
密码模式也很简单,直接通过用户名、密码获取令牌,流程如下:
密码模式
1、请求令牌
认证中心要求客户端输入用户名、密码,认证成功则颁发令牌,请求的url如下:
/oauth/token?
grant_type=password&
username=&
password=&
client_id=&
client_secret=
参数解析如下:
- grant_type:授权类型,密码模式固定值为password
- username:用户名
- password:密码
- client_id:客户端id
- client_secret:客户端的秘钥
2、返回令牌
上述认证通过,直接返回JSON数据,不需要跳转,如下:
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101
}
access_token则是颁发的令牌,refresh_token是刷新令牌,一旦令牌失效则携带这个令牌进行刷新。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>