You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:42:52