之前在《<font style=color:rgb(18, 18, 18);>使用 IdentityServer 保护 Web 应用(AntD Pro 前端 + SpringBoot 后端) - Jeff Tian的文章 - 知乎 》里,使用 spring-security-oauth2 对接了授权服务(Duende IdentityServer),来保护 Java 服务。这时候,该 Java 服务是属于资源服务器。

1681927161317 1e5b6077 ff03 4320 a1be 5e9d059ea37d

后来又在《<font style=color:rgb(18, 18, 18);>【已解决】spring-boot - 无效的 JWToken : kid is a required JOSE Header - Jeff Tian的文章 - 知乎 》里,以 Authing.cn 为授权服务的例子,详述了使用 spring-security-oauth2 时,资源服务器的配置。

今天,再次以这个 Authing.cn 的具体例子,详述一下从 spring-security-oauth2 升级到 spring-boot-starter-oauth2-resource-serve<font style=color:rgb(173, 186, 199);> 的步骤。升级后能同样对资源服务进行保护,并且有更好的扩展性。

写个测试先

在做具体升级前,先添加一些自动化的集成测试。所采用的 Java 项目,运行时依赖 MySQL 数据库。为了方便测试,参考《<font style=color:rgb(18, 18, 18);>借助 h2,加速 java 项目的自动化测试 - Jeff Tian的文章 - 知乎 》采用了 h2 内存数据库。

1681927622271 185e30c1 b99b 448d 8b8d bd0411abfaba

随后,添加了测试专属配置,仅在测试运行时启用 h2:

1681927675337 56bf1d6a 61cb 4ce9 857a 9743f3f099ba

然后,使用 MockMvc 写了第一个用例:

1681927732519 fa37cb17 0422 45f7 8fa6 e8888c676596

为什么要升级到 spring-boot-starter-oauth2-resource-serve

以上的测试用例,其实没有展示受保护的接口。这个项目中,有些接口是被保护起来的,但是 /friends 接口是开放的。不过,这要求你在调用时不能传入 token。如果传入了错误的或者过期的 token,这个接口会返回 401,给人以需要认证的感觉。

我这次升级的动力是希望对于开放接口,即使前端传了 token,也不做校验。一个方案就是在检测到是开放接口时,自动移除 token。这在 **spring-boot-starter-oauth2-resource-serve **中比较容易做到。

删除旧依赖,引入新依赖

1681928235651 9982ac4a 2f66 4eb6 bf81 2f896a315ece

删除旧的 java 配置,换成新的

1681928281650 6713ba0d 7e31 422c a583 7b253c7b7c92

1681928312090 69bf90b4 ed58 4203 a8d2 841695279e7d

配置文件的更新

1681928369498 5c5ae549 11f7 43b4 bbfe 0782ddab154c

添加新测试

之前的版本,如果传入错误的 token,开放接口也会返回 401 。写个测试用例,期待返回 200 OK,这个测试会失败。

1681928512751 063ae89e 92c2 491e ad0c 9147927d822b

接下来,需要做些扩展,以让它通过。

添加一个针对开放接口移除 token 的 filter

1681928836795 92c0808b 1996 45bf a1f2 5fcbeecbb90d

将这个 filter 加入到 java 配置中

1681928578464 583923ed b868 44bf a9ce e2b7a7b4c0cb

新的测试用例通过

1681928952101 c3cf21f2 2868 4bc8 a895 741cdd4eca90