OAuth2密码模式已死,最先进的Spring Cloud认证授权方案在这里

旧的Spring Security OAuth2停止维护已经有一段时间了,99%Spring Cloud微服务项目还在使用这些旧的体系,严重青黄不接。很多同学都在寻找新的解决方案,甚至还有念念不忘密码模式的。胖哥也在前面写了一篇解决思路的文章。好像还是不过瘾,今天看到这篇文章的同学有福了,问题将在这里得到解决。

方案

目前这应该是Spring生态中最新的解决方案,没有之一。先看下流程,微服务无关的其它的组件这里先屏蔽了,剩下图的几个组件:

详细流程为

  • ①用户向网关请求登录或者通过网关请求资源服务器的资源。

  • ②网关发现用户没有授权发起基于OAuth2授权码的OIDC流程,向授权服务器Id Server发起授权请求。

  • ③授权服务器Id Server收到授权请求重定向到用户登录页面要求用户登录认证,以发起授权。

  • ④用户输入用户名密码进行登录认证。

  • ⑤Id Server授权服务器处理用户认证并重定向到网关约定的OAuth2 Redirect URI,这个过程属于标准的OIDC授权码流程。

  • ⑥网关获得AccessTokenIdToken

    • 如果最初发起的是登录就重定向到/
    • 如果最初发起的是请求资源服务器资源就令牌中继重定向到对应的资源。
  • 资源服务器通过⑦⑧两个链路响应用户的请求。

请注意,上述流程中生成的AccessTokenIdToken不允许提供给用户侧,否则会引起中间人攻击,默认提供的是一个cookie策略,大部分情况下这种策略是够用的,如果你需要自定义必须深刻了解其机制,你可以通过我的Spring Security OAuth2专栏进行学习。

具体实现

根据上面的方案,我们需要三个应用,分别是网关Spring Cloud Gateway应用、资源服务器应用Resource ServerOAuth2授权服务器Id Server

Spring Cloud Gateway

Spring Cloud Gateway 应用,端口8080,它不仅仅是一个网关还是一个在授权服务器Id Server注册的OAuth2客户端,通过Id Server你可以在一分钟内完成配置。它需要配置到资源服务器的路由规则和令牌中继功能。核心配置为:

spring:
  application:
    name: gateway
  security:
    oauth2:
      client:
        registration:
          # 这里为客户端名称可自行更改
          gatewayclient:
            client-id: e4da4a32-592b-46f0-ae1d-784310e88423
            # 密码为注册客户端时的密码
            client-secret: secret
            # 只能选择一个
            redirect-uri: http://127.0.0.1:8080/login/oauth2/code/gatewayclient
            # 其它两种方式为refresh_token,client_credentials
            authorization-grant-type: authorization_code
            client-authentication-method: client_secret_basic
            scope: message.write,userinfo,message.read,openid
        provider:
          gatewayclient:
            # 要保证授权服务器地址可以被客户端访问
            issuer-uri: http://localhost:9000
  cloud:
    gateway:
      routes:
        - id: resource-server
          uri: http://127.0.0.1:8084
          predicates:
            - Path=/res/**
          filters:
            - TokenRelay

Resource Server

资源服务器就是我们平常编写的业务接口的服务器,端口这里定义为8084,它需要集成Spring Security及其Resource Server组件。它要负责定义资源接口的访问权限,例如:

         // 只有message.read才有资格访问资源/res/foo
        httpSecurity.authorizeRequests()
                .antMatchers("/res/foo").hasAnyAuthority("SCOPE_message.read")
 

另外它还要和授权服务器Id Server通讯获取AccessToken的解码公钥:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:9000/oauth2/jwks

获取解码公钥的原理在我的Spring Security OAuth2专栏有详细介绍,这里不再赘述。

Id Server

仓库地址:https://github.com/NotFound403/id-server 欢迎star,欢迎贡献。

Id Server是一个基于Spring Authorization Server的开源的授权服务器,它大大降低OAuth2授权服务器的学习使用难度,提供UI控制台,动态权限控制,方便OAuth2客户端管理,可一键生成Spring Security配置,开箱即用,少量配置修改就可部署,代码开源,方便二次开发,支持OAuth2四种客户端认证方式和三种授权模式。它是目前Spring安全生态中重要的组成部分,也是未来的技术发展趋势,更多信息请参阅Id Server项目仓库的介绍

Id Server在本文扮演的是OAuth2授权服务器的角色,负责对授权请求进行处理,维护客户端注册信息,授权用户信息,后续会加入IDP支持,各种三方登录的用户也可以动态在这里进行登录,就像这样:

联合登录

根据业务需要第三方OAuth2授权登录也能优雅的接入,当然,接入的登录方式需要OIDC或者OAuth2的支持。

DEMO以及使用方法

上述完整DEMOId Server的仓库中的samples下。使用方法:

  • 拉取Id Server项目并加载依赖。
  • IntelliJ IDEA中依次单独对samples文件夹下的所有项目的pom.xml进行右键菜单选中Add As Maven Project,这一步很重要。
  • 依次启动Id Servergatewayresource-server三个项目。

测试登录

  • 浏览器访问http://127.0.0.1:8080/login,点击http://localhost:9000
  • 输入用户名密码user/user
  • 能查看到认证信息就证明成功了,再次重申,在生产中该信息十分敏感,不应该直接对前端暴露。
  • 浏览器访问http://127.0.0.1:8080/res/foo,可以访问到资源服务器的资源。

另一种测试

关闭浏览器重新打开,浏览器访问http://127.0.0.1:8080/res/foo,你看看会发生什么?

总结

通过OAuth2客户端、Spring Cloud GatewayOAuth2授权服务器、OAuth2资源服务器的联动,你会发现授权码模式也可以实现完整的微服务认证授权,而且比密码模式更加安全。后续Id Server实现了联合登录之后,其它第三方登录也可以无缝集成进来。多多关注,更多先进的黑科技等着你。

关注公众号:码农小胖哥,获取更多资讯

个人博客:https://felord.cn

你可能感兴趣的:(OAuth2密码模式已死,最先进的Spring Cloud认证授权方案在这里)