Loading

SpringSecurityOauth2系列学习(一):初认Oauth2

系列导航

SpringSecurity系列

SpringSecurityOauth2系列

初认Oauth2

hello!我又来啦!

之前我们学习了前后端分离的SpringSecurity架构,但是在微服务满天飞的今天,前面学习的这种架构已经不适用了。

诶那么有没有一种适用于微服务的安全框架呢?

当然就是SpringSecurityOauth2了。

有的小伙伴一看,这不还是SpringSecurity嘛,后面加了一个Oauth2后缀,啥是Oauth2啊?

别急,我们先来看看Oauth2的概念

Oauth2的概念

先说OAuth,OAuth是Open Authorization的简写。

OAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是

OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与

密码就可以申请获得该用户资源的授权,因此OAuth是安全的。

OAuth2.0是OAuth协议的延续版本,但不向前兼容(即完全废止了OAuth1.0)。

使用场景

假设,A网站是一个打印照片的网站,B网站是一个存储照片的网站,二者原本毫无关联。

如果一个用户想使用A网站打印自己存储在B网站的照片,那么A网站就需要使用B网站的照片资源才行。

按照传统的思考模式,我们需要A网站具有登录B网站的用户名和密码才行,但是,现在有了OAuth2,只需要A网

站获取到使用B网站照片资源的一个通行令牌即可!这个令牌无需具备操作B网站所有资源的权限,也无需永久有

效,只要满足A网站打印照片需求即可。

这么听来,是不是有点像单点登录?NONONO!千万不要混淆概念!单点登录是用户一次登录,自己可以操作其

他关联的服务资源。OAuth2则是用户给一个系统授权,可以直接操作其他系统资源的一种方式。

但SpringSecurity的OAuth2也是可以实现单点登录的!

总结一句:SpringSecurity的OAuth2可以做服务之间资源共享,也可以实现单点登录!

角色说明

  • 应用(客户端):客户端就是一个要访问用户账号的应用,需要得到用户的允许后才可以得到授权
  • API服务(资源服务):资源服务通常提供API用于访问用户的授权客户端访问的信息
  • 授权服务:让用户批准或拒绝请求的服务,严格来说,认证不属于这个服务的职责,虽然往往认证和授权都在一个服务。当然授权服务也可以是资源服务
  • 用户(资源所有者):授权客户端访问资源服务器的主体

通常,作为作为OAuth2的客户端 ,需要上传这几个字段:

  • Application name:应用名
  • HomepageURL:主页,主要是域名
  • Authorization callback URL:回调地址,授权成功后返回的URL

然后系统对于每个客户端会生成Client ID(必要,应用工具唯一标识)和Client Secret(非必要,可以理解为应用的密码),请求授权要求客户端传入这两个值进行授权

OAuth2.0中主流的四种授权方式

为了说明四种模式先准备一张图

授权码模式(authorization code

  • 流程

说明:【A服务客户端】需要用到【B服务资源服务】中的资源

  1. 第一步:【A服务客户端】将用户自动导航到【B服务认证服务】,这一步用户需要提供一个回调地址,以备【B服务认证服务】返回授权码使用。

  2. 第二步:用户点击授权按钮表示让【A服务客户端】使用【B服务资源服务】,这一步需要用户登录B服务,也就是说用户要事先具有B服务的使用权限。

  3. 第三步:【B服务认证服务】生成授权码,授权码将通过第一步提供的回调地址,返回给【A服务客户端】。

    注意这个授权码并非通行【B服务资源服务】的通行凭证。

  4. 第四步:这个时候,通常会给用户弹出一个页面,询问用户是否同意授权给A服务,用户点击同意,然后【A服务认证服务】携带上一步得到的授权码向【B服务认证服务】发送请求,获取通行凭证token。

  5. 第五步:【B服务认证服务】给【A服务认证服务】返回令牌token和更新令牌refresh token。

  • 使用场景

授权码模式是OAuth2中最安全最完善的一种模式,应用场景最广泛,可以实现服务之间的调用,常见的微

信,QQ等第三方登录也可采用这种方式实现。

简化模式(implicit)

  • 流程

说明:简化模式中没有【A服务认证服务】这一部分,全部又【A服务客户端】与B服务交互,整个过程不再有授权码,token直接暴露在浏览器。

  1. 第一步:【A服务客户端】将用户自动导航到【B服务认证服务】,这一步用户需要提供一个回调地址,以备【B服务认证服务】返回token使用,还会携带一个【A服务客户端】的状态标识state。

  2. 第二步:用户点击授权按钮表示让【A服务客户端】使用【B服务资源服务】,这一步需要用户登录B服务,也就是说用户要事先具有B服务的使用权限。

  3. 第三步:【B服务认证服务】生成通行令牌token,token将通过第一步提供的回调地址,返回给【A服务客户端】。

  • 使用场景

    适用于A服务没有服务器的情况。比如:纯手机小程序,JavaScript语言实现的网页插件等。

密码模式(resource owner password credentials)

  • 流程
  1. 第一步:直接告诉【A服务客户端】自己的【B服务认证服务】的用户名和密码

  2. 第二步:【A服务客户端】携带【B服务认证服务】的用户名和密码向【B服务认证服务】发起请求获取token。

  3. 第三步:【B服务认证服务】给【A服务客户端】颁发token。

  • 使用场景

    此种模式虽然简单,但是用户将B服务的用户名和密码暴露给了A服务,需要两个服务信任度非常高才能使用。

客户端模式(client credentials)

  • 流程

    说明:这种模式其实已经不太属于OAuth2的范畴了。A服务完全脱离用户,以自己的身份去向B服务索取token。换言之,用户无需具备B服务的使用权也可以。完全是A服务与B服务内部的交互,与用户无关了。

  1. 第一步:A服务向B服务索取token。

  2. 第二步:B服务返回token给A服务。

  • 使用场景

    A服务本身需要B服务资源,与用户无关。

JWS/JWK

Oauth2中返回的token其实也有很多种类型,SpringSecurityOauth2中授权服务器如果不做配置,那么默认返回的其实只是一串UUID。

那么我们使用怎样的token呢?当然还是JWT啦!

SpringSecurityOauth2中授权服务器签发的token还是使用非对称加密进行签名,但是其内部已经实现了相关逻辑,不再需要我们自己去写逻辑,配置好之后直接使用即可。

不过这里还需要了解一个术语:JWS/JWK

JWT火爆之后,人们对于其安全性做了很多讨论,其签名也是人们讨论的话题之一。JWT支持使用不同的算法进行签名,但是没有一个统一的方式。

JWS就是JWT签名的验证数据完整性的不同的加密机制

JWK就是签名加密密钥的JSON结构。一般情况下,对于签名需要有一个不对称加密,需要有密钥对进行加密。

公钥和私钥。公钥加密需要私钥来解密,同样的私钥加密需要公钥来解密。

一般公钥和私钥放在不同的地方,私钥保存在服务器上面,而公钥保存在客户端。公钥可以公开,私钥保密。

签发token使用私钥加密,签名。token的内容是公开的,但是token的签名验证需要公钥去解密验证,没有私钥是伪造不出来私钥加密的签名的。只要验证成功,说明这个token是使用私钥签发的,是可以信任的

流程:

  1. 客户端请求Access Token,资源服务器返回一个使用JWS签名的一个JWT,这里的JWS包含一个Kid,其为一种加密形式的唯一标识,表示了应该使用说明方式进行加密。
  2. 客户端请求资源,将使用JWS签名的一个JWT传递给资源服务器,资源服务器会向授权服务器请求一个公钥,授权服务器会把JWK(即Kid对应的这种密钥结构)返回给资源服务器,之后资源服务器就使用这个公钥去验证签名,去验证权限。

加密流程

加密流程也就是创建JWT的过程

拿私钥进行非对称加密,将kid和其kid value写入jws的header中,然后在进行Claims声明进行编码

然后将jws header放入签名这个字段里面去,进行编码

最后就形成了有header,有cliams,有签名的一个jwt

解密流程

拿到JWT之后,去请求一个公钥,对这个JWT进行一个解析

解析完成之后,得到签名,然后取出其中Kid为key对应的Kid value

然后将Kid value设置到签名当中

然后在去验证签名是否正确

posted @ 2021-09-27 16:57  硝酸铜  阅读(1377)  评论(0编辑  收藏  举报