/api/**
的请求都转发到 api-service 进行处理。
负载均衡spring:
cloud.gateway.routes:
- id: api-service-route
uri: http://localhost:8080
predicates:
- Path=/api/**
filters:
- StripPrefix=1这个例子中,如果访问,gateway-service 会把对应的请求转到 ,实际进行处理的是 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
经过上面这些配置之后,我们就已经实现了一个比较简单的微服务架构下的网关服务了。