Spring Boot应用中验证Cognito JWT 实现API端点权限控制的步骤与代码
嘿,我刚接触JWT和Cognito的时候也完全懵圈,别担心,我把一步步的实现过程和代码都整理出来了,保证你能看懂!
手把手教你在Spring Boot中验证Cognito JWT并保护API端点
1. 先搞定依赖
首先得给Spring Boot项目加上必要的依赖,我们用Spring Security的OAuth2资源服务器模块来处理Cognito的JWT验证,这比自己手动解析JWT靠谱多了。
如果是Maven,在pom.xml里加:
<dependencies> <!-- Spring Security核心 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- OAuth2资源服务器,专门处理JWT验证 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> <!-- Web模块,用来写API --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
如果是Gradle,build.gradle里加:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'org.springframework.boot:spring-boot-starter-web' }
2. 配置Cognito相关参数
接下来在application.yml(或application.properties)里配置Cognito的信息,这些都能在AWS Cognito控制台找到:
spring: security: oauth2: resourceserver: jwt: # 你的Cognito用户池Issuer URI,格式:https://cognito-idp.{region}.amazonaws.com/{userPoolId} issuer-uri: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx # 你的Cognito客户端ID(对应JWT里的aud字段) audience: your-cognito-client-id
小提示:Issuer URI可以在Cognito用户池的「App integration」→「Domain name」下找到,或者直接按格式拼接;客户端ID在「App clients and analytics」里的App client ID栏。
3. 编写Spring Security配置类
这一步是核心,我们要告诉Spring Security哪些API需要验证JWT,以及如何验证Cognito的Token:
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.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // API服务不需要CSRF保护,直接关闭 .csrf(csrf -> csrf.disable()) // 配置请求权限规则 .authorizeHttpRequests(auth -> auth // 允许所有人访问公开端点(比如健康检查、公开API) .requestMatchers("/api/public", "/actuator/health").permitAll() // 所有/api开头的请求都需要验证JWT .requestMatchers("/api/**").authenticated() // 剩下的所有请求都需要认证 .anyRequest().authenticated() ) // 开启OAuth2资源服务器的JWT验证模式 .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt // 可选:自定义JWT转换器,把Cognito的Claims映射到Spring Security的Authentication .jwtAuthenticationConverter(new CognitoJwtAuthenticationConverter()) )); return http.build(); } }
如果想把Cognito里的用户角色(比如cognito:groups)映射到Spring Security的权限系统,可以写个自定义转换器:
import org.springframework.core.convert.converter.Converter; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; import java.util.Collection; import java.util.stream.Collectors; public class CognitoJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> { private final JwtGrantedAuthoritiesConverter defaultConverter = new JwtGrantedAuthoritiesConverter(); @Override public AbstractAuthenticationToken convert(Jwt jwt) { // 获取默认的权限(比如scope开头的) Collection<GrantedAuthority> authorities = defaultConverter.convert(jwt); // 从Cognito的Claims里获取自定义角色,转为Spring Security的权限格式 Collection<String> cognitoGroups = jwt.getClaimAsStringList("cognito:groups"); if (cognitoGroups != null) { authorities.addAll( cognitoGroups.stream() .map(group -> new SimpleGrantedAuthority("ROLE_" + group)) .collect(Collectors.toList()) ); } // 返回包含用户信息和权限的Authentication对象 return new JwtAuthenticationToken(jwt, authorities, jwt.getClaim("username")); } }
4. 编写受保护的API端点
现在写一个需要验证JWT才能访问的API,顺便演示如何获取JWT里的用户信息:
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class ProtectedController { // 公开端点:所有人都能访问 @GetMapping("/public") public String publicEndpoint() { return "这是公开API,不需要JWT就能访问!"; } // 受保护端点:必须带有效JWT才能访问 @GetMapping("/protected") public String protectedEndpoint(@AuthenticationPrincipal Jwt jwt) { // 从Jwt对象里获取用户的各种信息 String username = jwt.getClaim("username"); String email = jwt.getClaim("email"); return String.format("欢迎你,%s!你的邮箱是%s。这是受保护的API,只有持有有效JWT的用户才能访问。", username, email); } }
5. 测试验证
用Postman或curl测试:
- 访问
http://localhost:8080/api/public:不需要带任何Token,直接返回成功。 - 访问
http://localhost:8080/api/protected:- 不带
Authorization头:返回401 Unauthorized。 - 带
Authorization: Bearer <你的Cognito JWT Token>:正常返回用户信息。
- 不带
小提示:你可以从Cognito的登录流程(比如前端SDK、AWS CLI)获取id_token或access_token,两者都可以用于验证。
内容的提问来源于stack exchange,提问作者capedCoder
相关产品推荐
相关产品推荐

