Spring Cloud Gateway 基于 OAuth2.0 的身份认证

Posted 李博/Alexの技术海洋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Gateway 基于 OAuth2.0 的身份认证相关的知识,希望对你有一定的参考价值。

  在微服务中,我们将整个大业务根据各自细化的职责划分为多个独立的小服务,每个服务都会提供各自的 API 接口。但是,实际业务中我们不会将所有子服务接口单独暴露出来,我们需要有一个统一的入口为我们进行请求转发、负载均衡、访问认证等等操作。早期我们使用 Netflix Zuul 封装网关服务,现在我们使用 Spring Cloud Gateway 来处理入口请求。

  这里我会介绍如何编写一个网关服务,我会分为几个部分一一进行介绍。

请求转发

  Spring Cloud Gateway 可以通过代码或者配置文件指定路由,我还是习惯在配置文件里面操作。这里简单配置将所有 /api/** 的请求都转发到 api-service 进行处理。
spring:
cloud.gateway.routes:
- id: api-service-route
uri: http://localhost:8080
predicates:
- Path=/api/**
filters:
- StripPrefix=1

  这个例子中,如果访问 http://localhost:8082/api/hello,gateway-service 会把对应的请求转到 http://localhost:8080/hello,实际进行处理的是 api-service。

  StripPrefix 是 Spring Cloud Gateway 提供的 Gateway Filter,Spring Cloud Gateway 提供了众多预设的 Filters,你可以在 Spring Cloud Gateway 官方文档 中进行查询,可以根据自己的需求使用已有的 Filters 进行快速开发,当然也可以参考这些 Filters 的源码

自己封装自定义的 Filter。

负载均衡

  我们的后端服务通常是需要实现高可用的,将 user-service 和 gateway-service 注册到注册中心(我们使用 Consul),通过 spring.cloud.gateway.discovery.locator.enabled = true 启用服务发现,并搭配 lb:// 使用负载均衡(load balancer)。在 Spring Cloud Gateway 中,LoadBalancerClientFilter 负责处理 lb 请求并获取到真实请求地址。

spring.cloud.gateway:
discovery.locator.enabled: true
routes:
- id: api-service-route
uri: lb://api-service
predicates:
- Path=/api/**
filters:
- StripPrefix=1

身份认证

我们的认证中心是基于 Spring Security 实现的标准 OAuth2.0 认证服务,所以我们依然使用 spring-security-oauth2-resource-server 将 Gateway 作为一个 oauth2 client 进行集成。

技术图片

用户的访问基本上都是需要携带 JWT Token 的,gateway-service 在接收到请求之后,会向鉴权服务发送鉴权请求,获得授权之后可以得到当前访问的用户详细信息;如果检测到请求未经授权,那么 gateway-service 直接会返回未授权错误,保护内部服务访问安全。

理论上鉴权也可以通过自定义 gateway filter 来实现,不过我们希望可以尽可能多使用 spring-security 提供的能力,毕竟自己封装需要实现的东西还是有点多的。

Spring Cloud Gateway 只支持搭配 webflux 使用,所以我们后续使用了 @EnableWebFluxSecurity 注解。

我们将 gateway 作为一个 resource server 进行配置,毕竟 spring-security 帮我们做了很多事情,所以需要我们自己配置的代码很少。

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated();

http.oauth2ResourceServer().jwt();

return http.build();
}

因为我们的 authorization server 使用了 jwt token,jwt 很适合在纯 RESTful API 中作为无状态的认证凭证进行使用,搭配 spring security oauth2 的话,简单且好用。当然如果在某些场景下需要撤销某个 jwt token,也可以搭配 redis 进行管理。

我们在上面代码中声明了 gateway-service 作为一个简单的 resource server 并启用了 jwt,jwt token 通过公钥来验证有效性。因此我们需要指定 jwt 鉴权的公钥地址。

spring.security.oauth2.resourceserver.jwt:
jwk-set-uri: ‘http://localhost:8081/.well-known/jwks.json‘

经过上面这些配置之后,我们就已经实现了一个比较简单的微服务架构下的网关服务了。

以上是关于Spring Cloud Gateway 基于 OAuth2.0 的身份认证的主要内容,如果未能解决你的问题,请参考以下文章

基于Spring cloud gateway定制的微服务网关

Spring Cloud Gateway:基于ServerWebExchange修改请求或者响应内容

Spring Cloud Gateway:基于ServerWebExchange修改请求或者响应内容

004-spring cloud gateway-GatewayFilter Factories

Spring.Cloud Gateway——架构分析

Spring.Cloud Gateway——架构分析