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

如何为Spring Boot应用集成Amazon Cognito身份池实现Spring Security认证

嘿,刚好做过类似的场景,我来一步步给你讲清楚怎么在Spring Boot里验证这些AWS临时凭证,完成用户认证~

核心思路

我们要做的是验证客户端传来的临时AWS凭证的合法性,同时获取凭证对应的用户/角色身份信息,这样就能把它集成到Spring Boot的认证流程里,控制接口的访问权限。AWS的STS(Security Token Service)提供了GetCallerIdentity接口,专门用来干这件事——它能验证凭证是否有效,还能返回凭证关联的用户ID、ARN等关键信息。

具体步骤

1. 引入AWS SDK依赖

首先在你的Spring Boot项目里添加STS的SDK依赖,Maven的话在pom.xml里加:

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>sts</artifactId>
    <version>2.20.0</version> <!-- 建议用最新稳定版 -->
</dependency>

Gradle的话对应配置:

implementation 'software.amazon.awssdk:sts:2.20.0'

2. 编写凭证验证工具类

创建一个工具类,用客户端传来的临时凭证初始化STS客户端,调用GetCallerIdentity接口做验证:

import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.GetCallerIdentityResponse;
import org.springframework.stereotype.Component;

@Component
public class AwsCredentialValidator {

    public GetCallerIdentityResponse validateTempCredentials(String accessKeyId, String secretAccessKey, String sessionToken) {
        // 用客户端的临时凭证创建会话凭证对象
        AwsSessionCredentials tempSessionCreds = AwsSessionCredentials.create(
                accessKeyId,
                secretAccessKey,
                sessionToken
        );

        // 初始化STS客户端
        try (StsClient stsClient = StsClient.builder()
                .credentialsProvider(StaticCredentialsProvider.create(tempSessionCreds))
                .region(Region.US_EAST_1) // 换成你的AWS区域,也可以让客户端传区域
                .build()) {

            // 调用GetCallerIdentity验证凭证,有效则返回身份信息
            return stsClient.getCallerIdentity();
        }
    }
}

注意:如果凭证无效(比如过期、错误),STS客户端会抛出对应的异常(比如InvalidSessionTokenException、SdkException),我们后面可以捕获这些异常来判定认证失败。

3. 集成到Spring Security认证流程

接下来把验证逻辑加到Spring Security的过滤器里,这样每个请求都会先验证凭证:

3.1 自定义认证过滤器

创建一个OncePerRequestFilter,从请求头里拿凭证,调用工具类验证,验证通过后把用户信息放到Security上下文:

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import software.amazon.awssdk.services.sts.model.GetCallerIdentityResponse;
import software.amazon.awssdk.services.sts.model.StsException;

import java.io.IOException;
import java.util.Collections;

public class AwsTempCredentialAuthFilter extends OncePerRequestFilter {

    private final AwsCredentialValidator credentialValidator;

    public AwsTempCredentialAuthFilter(AwsCredentialValidator credentialValidator) {
        this.credentialValidator = credentialValidator;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 从请求头获取凭证(可以自己约定头字段名)
        String accessKey = request.getHeader("X-AWS-Access-Key");
        String secretKey = request.getHeader("X-AWS-Secret-Key");
        String sessionToken = request.getHeader("X-AWS-Session-Token");

        // 检查凭证是否存在,且当前没有已认证的用户
        if (accessKey != null && secretKey != null && sessionToken != null 
            && SecurityContextHolder.getContext().getAuthentication() == null) {

            try {
                // 验证凭证并获取身份信息
                GetCallerIdentityResponse identity = credentialValidator.validateTempCredentials(accessKey, secretKey, sessionToken);
                
                // 把身份信息封装成UserDetails(这里可以自定义你的UserDetails实现,包含更多信息)
                UserDetails userDetails = User.withUsername(identity.userId())
                        .password("") // 临时凭证不需要密码,这里填空或者固定值
                        .authorities(Collections.emptyList()) // 可以根据ARN或角色配置权限
                        .build();

                // 创建认证Token并放到Security上下文
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );
                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                
                SecurityContextHolder.getContext().setAuthentication(authToken);

            } catch (StsException e) {
                // 凭证验证失败,返回401
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write(String.format("Invalid AWS credentials: %s", e.getMessage()));
                return;
            }
        }

        // 继续执行后续过滤器
        filterChain.doFilter(request, response);
    }
}

3.2 配置Spring Security

把自定义过滤器加到Spring Security的配置里,替换或添加到认证流程:

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;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final AwsCredentialValidator credentialValidator;

    public SecurityConfig(AwsCredentialValidator credentialValidator) {
        this.credentialValidator = credentialValidator;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable()) // REST接口通常关闭CSRF
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated() // 所有请求都需要认证
                )
                // 把自定义过滤器加到UsernamePasswordAuthenticationFilter前面
                .addFilterBefore(new AwsTempCredentialAuthFilter(credentialValidator), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

4. 优化和注意事项

  • 凭证传递方式:建议用请求头传递凭证,比URL参数更安全;如果是HTTPS的话,凭证会被加密传输,不用担心泄露。
  • 异常处理:除了StsException,还要考虑其他可能的异常(比如网络问题),可以统一捕获SdkException来处理所有AWS SDK相关的错误。
  • 缓存优化:临时凭证有过期时间(可以从客户端的凭证里拿到expiration字段),可以缓存验证后的用户信息,减少STS的调用次数,提升接口性能。
  • 权限控制:你可以根据GetCallerIdentityResponse返回的arn或userId,结合你的业务逻辑配置用户的权限(比如某些接口只允许特定角色的用户访问)。

内容的提问来源于stack exchange,提问作者CharanRoot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:10:45