纯干货!Spring Cloud Gateway整合OAuth2.0 实现分布式统一认证授权

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 今天这篇文章介绍一下Spring Cloud Gateway整合OAuth2.0实现认证授权,涉及到的知识点有点多,有不清楚的可以看下陈某的往期文章。

今天这篇文章介绍一下Spring Cloud Gateway整合OAuth2.0实现认证授权,涉及到的知识点有点多,有不清楚的可以看下陈某的往期文章。

文章目录如下:

image.png


微服务认证方案


微服务认证方案目前有很多种,每个企业也是大不相同,但是总体分为两类,如下:

  1. 网关只负责转发请求,认证鉴权交给每个微服务商控制
  2. 统一在网关层面认证鉴权,微服务只负责业务


你们公司目前用的是哪种方案?


先来说说第一种方案,有着很大的弊端,如下:

  • 代码耦合严重,每个微服务都要维护一套认证鉴权
  • 无法做到统一认证鉴权,开发难度太大

第二种方案明显是比较简单的一种,优点如下:

  • 实现了统一的认证鉴权,微服务只需要各司其职,专注于自身的业务
  • 代码耦合性低,方便后续的扩展

下面陈某就以第二种方案为例,整合Spring Cloud Gateway+Spring Cloud Security 整合出一套统一认证鉴权案例。


案例架构


开始撸代码之前,先来说说大致的认证鉴权流程,架构如下图:

image.png


大致分为四个角色,如下


  • 客户端:需要访问微服务资源
  • 网关:负责转发、认证、鉴权
  • OAuth2.0授权服务:负责认证授权颁发令牌
  • 微服务集合:提供资源的一系列服务。


大致流程如下


1、客户端发出请求给网关获取令牌

2、网关收到请求,直接转发给授权服务

3、授权服务验证用户名、密码等一系列身份,通过则颁发令牌给客户端

4、客户端携带令牌请求资源,请求直接到了网关层

5、网关对令牌进行校验(验签过期时间校验....)、鉴权(对当前令牌携带的权限)和访问资源所需的权限进行比对,如果权限有交集则通过校验,直接转发给微服务

6、微服务进行逻辑处理

针对上述架构需要新建三个服务,分别如下:

image.png

案例源码目录如下:

image.png


认证授权服务搭建


很多企业是将认证授权服务直接集成到网关中,这么做耦合性太高了,这里陈某直接将认证授权服务抽离出来。

认证服务的搭建这里就不再细说了,上一篇文章中已经介绍的很清楚了:OAuth2.0实战!使用JWT令牌认证!

新建一个oauth2-cloud-auth-server模块,目录如下:

image.png

和上篇文章不同的是创建了JwtTokenUserDetailsService这个类,用于从数据库中加载用户,如下:

image.png

为了演示只是模拟了从数据库中查询,其中存了两个用户,如下:

  • user:具有ROLE_user权限
  • admin:具有ROLE_admin、ROLE_user权限

要想这个生效,还要在security的配置文件SecurityConfig中指定,如下图:

image.png

另外还整合了注册中心Nacos,详细配置就不贴了,可以看源码。


网关服务搭建


网关使用的是Spring Cloud Gateway,网关如何搭建这里就不再细说了,有不清楚的可以看之前文章:Spring Cloud Gateway夺命连环10问?

新建一个oauth2-cloud-gateway模块,目录如下图:

image.png


1、添加依赖


需要添加几个OAuth2.0相关的依赖,如下:

image.png


2、JWT令牌服务配置


使用JWT令牌,配置要和认证服务的令牌配置相同,代码如下:

image.png


3、认证管理器自定义


新建一个JwtAuthenticationManager,需要实现**

ReactiveAuthenticationManager**这个接口。

认证管理的作用就是获取传递过来的令牌,对其进行解析验签过期时间判定。

详细代码如下:

image.png

逻辑很简单,就是通过JWT令牌服务解析客户端传递的令牌,并对其进行校验,比如上传三处校验失败,抛出令牌无效的异常。

抛出的异常如何处理?如何定制返回的结果?

这里抛出的异常可以通过Spring Cloud Gateway的全局异常进行捕获,这个内容在Spring Cloud Gateway夺命连环10问?这篇文章有详细的介绍。下面只贴出关键代码,如下:

image.png


4、鉴权管理器自定义


经过认证管理器JwtAuthenticationManager认证成功后,就需要对令牌进行鉴权,如果该令牌无访问资源的权限,则不允通过。

新建JwtAccessManager,实现**

ReactiveAuthorizationManager**,代码如下:

image.png

这里的逻辑很简单,就是取出令牌中的权限和当前请求资源URI的权限对比,如果有交集则通过。

①处的代码什么意思?

这里是直接从Redis中取出资源URI对应的权限集合,因此实际开发中需要维护资源URI和权限的对应关系,这里不细说,为了演示,陈某直接在项目启动的时候向Redis中添加了两个资源的权限,代码如下:

image.png

注意:实际开发中需要维护资源URI和权限的对应关系。

②处的代码什么意思?

这处代码就是取出令牌中的权限集合

③处的代码什么意思?

这处代码就是比较两者权限了,有交集,则放行。


5、令牌无效或者过期时定制结果


在第4步,如果令牌失效或者过期,则会直接返回,这里需要定制提示信息。

新建一个**

RequestAuthenticationEntryPoint,实现

ServerAuthenticationEntryPoint**,代码如下:

image.png


6、无权限时定制结果


在第4步鉴权的过程中,如果无该权限,也是会直接返回,这里也需要定制提示信息。

新建一个**

RequestAccessDeniedHandler,实现ServerAccessDeniedHandler**,代码如下:

image.png


7、OAuth2.0相关配置


经过上述6个步骤,相关组件已经准备就绪,现在直接配置到OAuth2.0中。

新建SecurityConfig这个配置类,标注注解 @EnableWebFluxSecurity,注意不是 @EnableWebSecurity,因为Spring Cloud Gateway是基于Flux实现的。详细代码如下:

需要配置的内容如下:

  • 认证过滤器,其中利用了认证管理器对令牌进行校验
  • 鉴权管理器、令牌失效异常处理、无权限访问异常处理
  • 白名单配置
  • 跨域过滤器的配置


8、全局过滤器定制


试想一下:网关层面认证鉴权成功后,下游微服务如何获取到当前用户的详细信息?

陈某这里是将令牌携带的用户信息解析出来,封装成JSON数据,然后通过Base64加密,放入到请求头中,转发给下游微服务。

这样一来,下游微服务只需要解密请求头中的JSON数据,即可获取用户的详细信息。

因此需要在网关中定义一个全局过滤器,用来拦截请求,解析令牌,关键代码如下:

上述代码逻辑如下:

  • 检查是否是白名单,白名单直接放行
  • 检验令牌是否存在
  • 解析令牌中的用户信息
  • 封装用户信息到JSON数据中
  • 加密JSON数据
  • 将加密后的JSON数据放入到请求头中

好了,经过上述8个步骤,完整的网关已经搭建成功了。


订单微服务搭建


由于在网关层面已经做了鉴权了(细化到每个URI),因此微服务就不用集成Spring Security单独做权限控制了。

因此这里的微服务也是相对比较简单了,只需要将网关层传递的加密用户信息解密出来,放入到Request中,这样微服务就能随时获取到用户的信息了。

新建一个oauth2-cloud-order-service模块,目录如下:

image.png

新建一个过滤器AuthenticationFilter,用于解密网关传递的用户数据,代码如下:

image.png

新建两个接口,返回当前登录的用户信息,如下:

image.png

注意:以上两个接口所需要的权限已经放入到了Redis中,权限如下:

  • /order/login/info:ROLE_admin和ROLE_user都能访问
  • /order/login/admin:ROLE_admin权限才能访问

image.png


为什么要将URI和权限放入Redis?


在网关的鉴权管理器那里是直接从Redis中获取URI对应的权限,然后和令牌中的权限比较,为什么要这样做?

这也是目前企业中比较常用的一种方式,将鉴权完全放在了网关层面,也实现了动态权限校验。当然有些是直接将接口的权限控制在每个微服务中。

采用陈某的这种方案需要另外维护URI和权限的对应关系,当然这种难度很低,便于实现。

只是一种方案,具体是否选用还要考虑到架构层面。


测试


同时启动上述三个服务,如下:

image.png

1、用密码模式登录user,获取令牌,如下

image.png

2、使用user用户的令牌访问/order/login/info接口,如下

image.png

可以看到成功返回了,因为具备ROLE_user权限。

3、使用user用户的令牌访问/order/login/admin接口,如下

image.png

可以看到直接返回了无权限访问,直接在网关层被拦截了。


总结


本篇文章只是简单的整合了网关+OAuth2.0,实际开发中还有一些细节待完善,由于文章篇幅限制,后续介绍......

相关文章
|
1月前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
|
2月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
457 3
|
1月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
113 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
3月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
238 0
|
4月前
|
缓存 监控 Java
说一说 SpringCloud Gateway 堆外内存溢出排查
我是小假 期待与你的下一次相遇 ~
578 5
|
4月前
|
Java API Nacos
|
5月前
|
人工智能 负载均衡 Java
Spring AI Alibaba 发布企业级 MCP 分布式部署方案
本文介绍了Spring AI Alibaba MCP的开发与应用,旨在解决企业级AI Agent在分布式环境下的部署和动态更新问题。通过集成Nacos,Spring AI Alibaba实现了流量负载均衡及节点变更动态感知等功能。开发者可方便地将企业内部业务系统发布为MCP服务或开发自己的AI Agent。文章详细描述了如何通过代理应用接入存量业务系统,以及全新MCP服务的开发流程,并提供了完整的配置示例和源码链接。未来,Spring AI Alibaba计划结合Nacos3的mcp-registry与mcp-router能力,进一步优化Agent开发体验。
2115 15
|
6月前
|
存储 负载均衡 测试技术
ACK Gateway with Inference Extension:优化多机分布式大模型推理服务实践
本文介绍了如何利用阿里云容器服务ACK推出的ACK Gateway with Inference Extension组件,在Kubernetes环境中为多机分布式部署的LLM推理服务提供智能路由和负载均衡能力。文章以部署和优化QwQ-32B模型为例,详细展示了从环境准备到性能测试的完整实践过程。
|
10月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
807 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
7月前
|
存储 Java 文件存储
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储
本文介绍了如何基于Spring Boot 3和MinIO实现分布式文件存储。随着应用规模扩大,传统的单机文件存储方案难以应对大规模数据和高并发访问,分布式文件存储系统成为更好的选择。文章详细讲解了MinIO的安装、配置及与Spring Boot的整合步骤,包括Docker部署、MinIO控制台操作、Spring Boot项目中的依赖引入、配置类编写及工具类封装等内容。最后通过一个上传头像的接口示例展示了具体的开发和测试过程,强调了将API操作封装成通用工具类以提高代码复用性和可维护性的重要性。
1435 7
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储