在微服务架构中,Spring Cloud Gateway 是一种流行的API网关解决方案,它可以处理路由、负载均衡、安全、监控等任务。通过Spring Cloud Gateway,我们可以实现路径重写、登录拦截以及跨域配置等功能。本文将介绍如何搭建一个Spring Cloud Gateway网关,并实现上述功能。
在搭建Spring Cloud Gateway网关之前,确保你的项目结构如下:
首先,确保你的pom.xml
中包含以下依赖:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Spring Cloud Starter Security (用于统一登录模块) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Boot Starter OAuth2 Resource Server (用于JWT解析) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<!-- 其他依赖 -->
</dependencies>
确保你已经在pom.xml
中添加了Spring Cloud BOM管理和Spring Boot版本的相关配置。
在application.yml
中配置路由和过滤器:
spring:
cloud:
gateway:
routes:
- id: serviceA
uri: http://localhost:8081
predicates:
- Path=/serviceA/**
filters:
- StripPrefix=1
- RewritePath=/serviceA/(?<segment>.*), /${segment}
- id: serviceB
uri: http://localhost:8082
predicates:
- Path=/serviceB/**
filters:
- StripPrefix=1
- RewritePath=/serviceB/(?<segment>.*), /${segment}
default-filters:
- AddRequestHeader=Default-Header, DefaultValue
/serviceA/**
和 /serviceB/**
路由到相应的服务。StripPrefix
去掉前缀,RewritePath
重写路径。在Gateway
中配置跨域,使用Spring Cloud Gateway的GlobalCorsProperties
:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}
在application.yml
中配置跨域:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: '*'
allowedMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowedHeaders:
- '*'
allowCredentials: true
在application.yml
中配置安全策略和认证服务器:
spring:
security:
oauth2:
resourceserver:
jwt:
# 设置 JWT 解析器
jwk-set-uri: http://auth-server/.well-known/jwks.json
在 Spring Boot 应用中创建一个配置类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/swagger-ui.html", "/v2/api-docs");
}
}
创建一个认证过滤器,用于拦截请求和验证token:
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 从请求中提取 JWT token
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
// 解析并验证 token
// 如果验证成功,设置 SecurityContext
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
}
通过以上步骤,我们成功地使用Spring Cloud Gateway搭建了一个网关服务,并实现了以下功能:
这种配置方式可以有效地将认证、授权、跨域处理等问题集中在网关层,实现统一管理,简化各微服务的开发与维护。希望这篇文章能帮助你在实际项目中顺利搭建和配置Spring Cloud Gateway。