SpringSecurity 前后分离的实现有几种不同的组合方式,在网上收集了各种各样的实现之后

总结一下两种实现方式

不同的验证结构

  1. 只使用 Securtiy ,通过添加自行实现的 JWT 过滤器到 Security 的过滤器链中。来实现鉴权,

通过重写各种逻辑 handeler 来实现更改默认的页面跳转为Json 数据响应。

  1. 使用 oauth2 的 Password 模式,通过 oauth2 来进行鉴权。由于可以直接使用本身的 handeler

可以不重写,但是由于自身处理的响应信息内容过少,还是需要重写。

注意:使用oauth2时 clien_id 和 grant_type 不可缺少,否则将会进入 Http Basic 模式

scope 虽然在当前模式没有什么意义,但是至少需要在客户端或服务端定义一个。在Jwt 签名中需要使用它。

oauth2注意的问题

oauth2 实际上需要维护 客户端 和 用户 两个身份的信息,需要额外注意这一点。它比只使用 Securtiy 来说

多出了 客户端 的身份信息。需要注意维护这个身份相关的内容,在不提供第三方授权时,也可使用内存维护。

使用 oauth2 协议不需要配置 WebSecurity 只需要配置 oauth2 的两个认证服务器和资源服务器即可。

SpringSecurity-oauth2

主要使用ouath2的password模式进行认证,依赖使用 spring-security-oauth2 扩展 spring-boot-starter-security

由于使用了oauth2 协议,所以除了可以使用密码模式以为,也可以使用其他三种模式,来授权第三方登陆。

但对于单体应用来说,使用 oauth2 协议 需要资源服务器和认证服务器配置在同一应用下,拦截器链很可能产生冲突。

不过 ouath2 提供了自带的Token 刷新,可以减少部分开发工作。配合 spring-security-oauth2-jose 可以使用 JWT 进行认证。

其中JOSE 是指 Javascript 对象签名和加密 它包含以下4个组件

  • JSON Web Token (JWT)

  • JSON Web Signature (JWS)

  • JSON Web Encryption (JWE)

  • JSON Web Key (JWK)

需要注意的 oauth2 是三方信任的关系,保证了 用户-资源-客户端 的相互信任,所以有两条信任链,与基础的 用户-资源 信任方式不同。

它还有一个基于cloud的自动配置 spring-cloud-starter-oauth2 。

这里需要注意springBoot 的版本 由于 springBoot 1.5.x 使用的时 security 4 而 2.x.x 使用的是 security 5

相关配置和依赖项都有所不同,其中 springBoot 1.5.x 使用 spring-security-oauth2 和 spring-security-jwt

不能使用 2.x.x 的 spring-cloud-starter-oauth2 和 spring-security-oauth2-jose。

而且 2.x.x 的 httpbasic 配置方式也发生了改变,配置文件配置 basicHttp 不再生效,BasicHttp 验证页面变得好看了。

但严格来说,对于前后分离来讲,页面路由应由前端进行路由,后端只需提供数据。但 oauth2 授权码模式 会跳转到自己的登陆页面上,而不是返回数据。

提示前端来进行路由,这就需要重写SpringSecurity的各种处理器来实现发送数据,由于SpringSecurity早先是基于后端渲染级权限控制的。

所以它的一系列的登陆逻辑处理器都需要被重写。

SpringSecurity-jwt

依赖 spring-security-jwt 两种方法都需要 spring-boot-starter-security。

完成依靠重写 SpringSecurity 的各种处理器来实现分离控制。不进行跳转。由于基本完全基于手工代码重写实现,

基本不会存在 oauth2 的多服务器拦截器链冲突问题,但相关的令牌生命周期和令牌刷新都需要自行实现。

oauth2 的相关问题

首先是4种模式:

  1. 授权码
  2. 简化码
  3. 密码
  4. 客户端

授权码是最安全也最复杂的模式,对于第三方客户端来说,可以完全保护用户资源和用户信息。

简化码主要是在授权码基础上减少了一步由第三方客户端后台使用授权码换取资源访问许可令牌的环节,

从而令第三方直接获得资源访问令牌,无需使用授权码。

密码模式则是通过 用户名 密码 和 客户端ID 及客户端密码 发送到认证服务器,直接换取资源访问令牌。

客户端模式由认证服务器直接验证客户端身份信息,只需要客户端ID和客户端密码即可换取资源访问令牌。

对于刷新令牌,客户端和简化码模式不支持刷新。

令牌刷新问题

主要有两种刷新方式:

浏览器主动刷新

浏览器每次访问后端端口前先对存储在浏览器中的token解析,获取过期时间。然后与当前系统时间进行比较,

小于一定时间则调用服务器的令牌刷新端口获取新的访问令牌,最后用新的访问令牌去访问服务器资源。

不过由于浏览器需要更新令牌之后才能访问资源,所以在执行刷新令牌时浏览器访问延迟会提高。

服务器被动刷新

浏览器每次访问后对令牌进行检查与存储在本地的令牌进行比较,如果令牌刷新则进行更新本地存储。

使用JWT则不应使用服务器被动刷新,因为JWT无状态特性不应在服务器上保存状态

一般来说,服务器对接口的访问每次都会进行验证,如果令牌过期但可以刷新那么就继续执行访问,返回时发送新的令牌。