在现代Web应用程序中,确保客户端与后端服务之间的通信安全至关重要。API Gateway 作为所有客户端请求的单一入口点,负责处理身份认证、授权以及向后端微服务的路由。JWT (JSON Web Tokens) 提供了一种紧凑且自包含的方式,能够在各方之间安全地传输信息。
本文将演示如何使用 JWT 在 Spring Boot API Gateway 中实现身份认证和授权,并配合一个示例微服务进行讲解。
前置条件
- 已安装 Java Development Kit
- 已安装 Maven 或 Gradle 用于依赖管理
- 对 Spring Boot 和 Spring Cloud 有基本了解
- 已安装并运行 MySQL
概述:API Gateway 与 JWT
API Gateway:
- 充当反向代理和中心安全节点。
- 处理身份认证和授权。
- 将请求路由到相应的微服务。
JWT:
- 将用户身份和角色编码在一个紧凑的 JSON 对象中。
- 用于无状态身份认证。
- 确保客户端与服务之间信息传输的安全性。
项目搭建
API Gateway 项目
让我们使用 Spring Initializr 来创建一个 Spring Boot 项目,并添加以下依赖:
- Spring Web
- Spring Gateway Routing
- Spring Security
- Lombok
- MySQL Driver
- Spring DevTools
应用端口: 8080
文件夹结构:标准的 Spring Boot Maven 结构,包含 model、repository、service、config 和 controller 包。
应用配置
我们可以将 application.properties 重命名为 application.yml 并进行如下配置:
> server:
>
> port: 8080
>
>
>
> spring:
>
> application:
>
> name: api-gateway
>
> datasource:
>
> url: jdbc:mysql://localhost:3306/jwt
>
> username: root
>
> password:
>
> driver-class-name: com.mysql.cj.jdbc.Driver
>
> jpa:
>
> hibernate:
>
> ddl-auto: update
>
> show-sql: true
>
> cloud:
>
> gateway:
>
> routes:
>
> – id: example-service
>
> uri: http://localhost:8081
>
> predicates:
>
> – Path=/example/
>
> default-filters:
>
> – DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
>
>
>
> jwt:
>
> secret: mySecretKey
用户管理
用户实体
Java
CODEBLOCK_797dbb0b
认证模型
AuthenticationRequest.java:
Java
CODEBLOCK_5165bcee
AuthenticationResponse.java:
Java
CODEBLOCK_663f6fc0
用户仓库
Java
CODEBLOCK_b970bde0
安全配置
SecurityConfig.java
Java
CODEBLOCK_c847ef66
JwtAuthenticationFilter.java
验证每个传入请求的 JWT 并设置认证上下文。
Java
“
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
public JwtAuthenticationFilter(JwtUtil jwtUtil) { this.jwtUtil = jwtUtil; }
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
String username = null;