旧的 Spring Security OAuth2 停止维护已经有一段时间了, 99% 的 Spring Cloud 微服务项目还在使用这些旧的体系,严重青黄不接。很多同学都在寻找新的解决方案,甚至还有念念不忘密码模式的。胖哥也在前面写了一篇解决思路的文章。好像还是不过瘾,今天看到这篇文章的同学有福了,问题将在这里得到解决。
方案
目前这应该是 Spring 生态中最新的解决方案,没有之一。先看下流程,微服务无关的其它的组件这里先屏蔽了,剩下图的几个组件:
详细流程为 :
-
①用户向网关请求登录或者通过网关请求资源服务器的资源。
-
②网关发现用户没有授权发起基于 OAuth2 授权码的 OIDC 流程,向授权服务器Id Server发起授权请求。
-
③授权服务器Id Server收到授权请求重定向到用户登录页面要求用户登录认证,以发起授权。
-
④用户输入用户名密码进行登录认证。
-
⑤Id Server授权服务器处理用户认证并重定向到网关约定的 OAuth2 Redirect URI ,这个过程属于标准的 OIDC 授权码流程。
-
⑥网关获得 AccessToken 和 IdToken :
- 如果最初发起的是登录就重定向到
/
。 - 如果最初发起的是请求资源服务器资源就令牌中继重定向到对应的资源。
- 如果最初发起的是登录就重定向到
-
资源服务器通过⑦⑧两个链路响应用户的请求。
请注意,上述流程中生成的 AccessToken 和 IdToken 不允许提供给用户侧,否则会引起中间人攻击,默认提供的是一个 cookie 策略,大部分情况下这种策略是够用的,如果你需要自定义必须深刻了解其机制,你可以通过我的 Spring Security OAuth2专栏 进行学习。
具体实现
根据上面的方案,我们需要三个应用,分别是网关 Spring Cloud Gateway 应用、资源服务器应用 Resource Server 和 OAuth2 授权服务器 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
仓库地址:github.com/NotFound403… 欢迎star,欢迎贡献。
Id Server 是一个基于 Spring Authorization Server 的开源的授权服务器,它大大降低 OAuth2 授权服务器的学习使用难度,提供 UI 控制台,动态权限控制,方便 OAuth2 客户端管理,可一键生成 Spring Security 配置,开箱即用,少量配置修改就可部署,代码开源,方便二次开发,支持 OAuth2 四种客户端认证方式和三种授权模式。它是目前 Spring 安全生态中重要的组成部分,也是未来的技术发展趋势, 更多信息请参阅Id Server项目仓库的介绍 。
Id Server 在本文扮演的是 OAuth2 授权服务器的角色,负责对授权请求进行处理,维护客户端注册信息,授权用户信息,后续会加入 IDP 支持,各种三方登录的用户也可以动态在这里进行登录,就像这样:
根据业务需要第三方 OAuth2 授权登录也能优雅的接入,当然,接入的登录方式需要 OIDC 或者 OAuth2 的支持。
DEMO以及使用方法
上述完整 DEMO 在 Id Server 的仓库中的samples
下。使用方法:
- 拉取 Id Server 项目并加载依赖。
- 在 IntelliJ IDEA 中依次单独对
samples
文件夹下的所有项目的pom.xml
进行右键菜单选中 Add As Maven Project ,这一步很重要。 - 依次启动 Id Server 、 gateway 、 resource-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 Gateway 、 OAuth2 授权服务器、 OAuth2 资源服务器的联动,你会发现授权码模式也可以实现完整的微服务认证授权,而且比密码模式更加安全。后续 Id Server 实现了联合登录之后,其它第三方登录也可以无缝集成进来。多多关注,更多先进的黑科技等着你。
关注公众号:Felordcn获取更多资讯