微信搜索
江南一点雨

OAuth2,想说懂你不容易

最近几篇都是 OAuth2 相关的,因为松哥最近又在搞 OAuth2。

四月份的时候连载了十来篇文章介绍 OAuth2(公号后台回复 OAuth2 可以下载教程),那个时候用的是 Spring Cloud OAuth2,很多小伙伴可能不清楚 Spring Cloud OAuth2 和 Spring Security OAuth 以及 Spring Security5.x 之间的关系,今天我就来和大家聊一聊 OAuth 协议在 Spring 家族落地的故事。

历史

大家都知道,OAuth、OAuth2 都是一种协议,协议需要通过代码落地。

在 2018 年以前,如果我们想在 Spring 构建的项目中使用 OAuth2 协议,首选的框架就是 Spring Security OAuth 这个开源项目,也就是如下依赖:

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>

这个项目是十年前 Spring 引入的一个社区驱动的开源项目,经过数十年的发展,它已经非常成熟,可以支持大部分 OAuth 规范,包括资源服务器客户端授权服务器等。

然而数十年前 Spring 家族在 Java 领域的影响力远不如今天这样庞大,虽然 Spring 家族中 OAuth2 的落地项目是 Spring Security OAuth,但是很多 Spring 子项目并不买账,他们自己又搞了一套跟 Spring Security OAuth 类似的 OAuth2 的实现。

数十年间,OAuth 协议也从 1.0 变成了 2.0,以前没有的 JWT 令牌现在也广泛应用起来了,而 Spring Security OAuth 竟然还支持已经市场抛弃的 OAuth1.0。

种种迹象表明,这个创建于十年前的 Spring Security OAuth 项目架构似乎需要来一次大换血了。

于是在 2018 年 1 月 30 号,官方说要逐渐停止 Spring Security OAuth 开源项目,将 OAuth2 的具体实现,在 Spring Security5.x 中进行重构。换句话说,以后如果想在 Spring 中使用 OAuth2,直接引入 Spring Security 依赖就行了,无需再额外引入 OAuth2 依赖。

从那个时候起,Spring Security OAuth 开源项目就处于维护状态了,现在当我们利用 IDEA 创建一个 Spring Boot 项目时,依赖选项就有没有 Spring Security OAuth 了,如果需要我们只能手动添加。手动添加并使用后,你会发现满屏的删除线:

所以现在并不建议大家再去用这个已经过时的东西。有小伙伴可能会问,那你四月份写的 OAuth2 教程里边,相同的代码怎么都没有删除线呢?这个松哥一会给大家解释。

OAuth2 框架主要包含三种角色:

  • 客户端
  • 资源服务器
  • 授权服务器

对于普通开发者而言,接触最多的就是客户端了。你想让你的项目接入 QQ 登录、接入微信登录,你所做的事情就是 OAuth2 客户端的开发,现在在 Spring Security5.x 中,可以直接在 Spring Security 配置的基础上快速配置 OAuth2 客户端,类似下面这样:

class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
        http.oauth2Login(Customizer.withDefaults());
        http.oauth2Client();
    }
}

以前如果是 Spring Security OAuth 依赖的话,我们要通过 @EnableXXX 去开启客户端,现在在 Spring Security5.x 中重构之后,再去配置 OAuth2 客户端只需要通过一个方法就能搞定,还是非常方便的。

在少数场景下,你可能就是 QQ、微信的一方,你需要提供自己的登录服务给别人使用,这个时候就需要你开发资源服务器和授权服务器了。

在最新的 Spring Security5.x 中,我们可以通过如下方式开启资源服务器:

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer()
            .opaqueToken().introspectionUri(introspectionUri)
            .introspectionClientCredentials(clientId, clientSecret);
}

可以看到,都是在 Spring Security 的配置上进行配置,非常方便。

而授权服务器,则不包含在 Spring Security5.x 中。

在 2019.11.14 日,Spring 官方本来说是要放弃对授权服务器的支持了,因为现在市面上能用的授权服务器太多了,例如 keycloak、Nimbus SDK、Apache Oltu 以及 Vertx-auth-oauth2 等,这些开源的授权服务器都比较成熟稳定,用起来也蛮好用的。

然而广大开发者并不答应,在争吵了几个月之后,官方宣布了另外一个开源项目 Spring Authorization Server,这个项目用来构建授权服务器。目前该项目已经发布了 0.0.1 版,松哥也抽空体验了一把,功能较少,BUG 较多,官方给的 DEMO 都跑不起来,大家如果想体验这个项目,建议下载最新的源码去编译使用,这样可能问题反而少一些,而不是直接使用 0.0.1 版。

现状

现在当我们创建一个 Spring Boot 项目时,选择 OAuth2 依赖的时候,有两个地方可以选择:

两个都能用,但是有差异。

先说上面的。

在 Security 分类中,OAuth2 被细分为 OAuth2 Client、OAuth2 Resource Server,但是没有 Authorization Server,这就是目前最新的方案,Spring Security 中将不提供授权服务器。

如果你的项目是 OAuth2 客户端,那就选择 OAuth2 Client 依赖,如果是 OAuth2 资源服务器,那就选择 OAuth2 Resource Server 依赖。如果是授权服务器,那就。。。。用第三方开源项目吧。

如果选择的是 Security 中的这些依赖,那么像 @EnableResourceServer、ResourceServerConfigurerAdapter 这些注解或者类都是没有的,需要按照最新的方式去配置。

如果你是一个比较恋旧的人,还舍不得曾经的配置方式,但是又不想使用 Spring Security OAuth 开源项目,因为有烦人的删除线,那么你可以选择 Spring Cloud Security 中的 Cloud OAuth2 依赖。

这是针对 Spring Cloud 环境,对 Spring Security 做的一些封装,这个里边的 OAuth2 其实还是 Spring Security OAuth 中的那一套东西,不同的是,这里没有删除线,松哥四月份写的 OAuth2 教程,用的就是 Spring Cloud Security,所以项目打开后你都看不到删除线。

未来等 OAuth2 在 Spring Security5.x 中的实现稳定下来之后,相信 Spring Cloud Security 这边也会逐步跟进,大家期待的大统一的局面就会来临。

迁移

如果你需要将旧的 OAuth2 项目用最新的方式重构,那么可以参考这个迁移文档,里边有很多 DEMO:https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Migration-Guide。

小结

作为 Java 工程师,Spring 家族的产品还是用过不少,但是没有哪个项目像 OAuth2 这么混乱这么让人纠结,初学者在选择 OAuth2 依赖时绝对是一脸懵。希望这篇文章能给大家一点启发,小伙伴们在 OAuth2 这块要是有一些使用经验或者见解,也欢迎大家投稿哦。

赞(2)
未经允许不得转载:江南一点雨 » OAuth2,想说懂你不容易
分享到: 更多 (0)
扫码关注微信公众号【江南一点雨】,回复 1024,查看松哥原创 Java 实战教程(图文+视频)。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

专注 Java 一百年

关注我们国际站