2. 什么是 Amazon Cognito?

Amazon Cognito 是一个用户身份与数据同步服务,它帮助我们轻松管理跨设备的用户数据。

使用 Cognito,我们可以:

✅ 创建、认证和授权用户
✅ 为使用 Google、Facebook 或 Twitter 等公共身份提供商的用户创建身份
✅ 将应用的用户数据以键值对形式保存


3. 环境准备

3.1. Amazon Cognito 配置

作为身份提供商,Cognito 支持以下 OAuth 2.0 授权类型:

  • authorization_code(授权码模式)
  • implicit(隐式模式)
  • client_credentials(客户端凭证模式)

本例中我们使用的是 授权码模式(authorization_code)

配置步骤如下:

  1. 创建用户池(User Pool)
  2. 添加用户(用于登录 Spring 应用)
  3. 创建 App Client
  4. 配置 App Client

⚠️ 注意:

  • 回调地址(CallbackURL) 必须与 Spring 配置中的 redirect-uri 一致:

    http://localhost:8080/login/oauth2/code/cognito
    
  • 允许的 OAuth 流(Allowed OAuth flow) 必须选择 Authorization code grant

  • 允许的 OAuth 范围(Allowed OAuth scope) 必须包含 openid

  • 同时,还需要为用户池分配一个 User Pool Domain,以便跳转到 Cognito 的登录页面

3.2. Spring Boot 配置

我们需要引入以下两个依赖:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>

然后在 application.yml 中添加如下配置:

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            clientId: your-client-id
            clientSecret: your-client-secret
            scope: openid
            redirect-uri: http://localhost:8080/login/oauth2/code/cognito
            clientName: SpringCognitoClient
        provider:
          cognito:
            issuerUri: https://cognito-idp.{region}.amazonaws.com/{poolId}
            user-name-attribute: cognito:username

📌 替换说明:

  • your-client-idyour-client-secret 替换为你在 App Client 中创建的客户端 ID 和密钥
  • {region} 替换为你的用户池所在区域,例如 us-east-1
  • {poolId} 替换为你的用户池 ID

3.3. Spring Security 配置类

接下来添加 Spring Security 配置类,启用 OAuth2 登录功能:

@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(Customizer.withDefaults())
            .authorizeHttpRequests(authz -> authz.requestMatchers("/")
                .permitAll()
                .anyRequest()
                .authenticated())
            .oauth2Login(Customizer.withDefaults())
            .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessUrl("/"));
        return http.build();
    }
}

📌 说明:

  • 启用了 CSRF 保护
  • 根路径 / 允许匿名访问
  • 所有其他请求都需要认证
  • 启用 .oauth2Login() 以启用 OAuth2 登录流程
  • .logout() 配置了登出成功跳转路径

4. 添加登录页面

我们使用 Thymeleaf 编写一个简单的登录页面:

<div>
    <h1 class="title">OAuth 2.0 Spring Security Cognito Demo</h1>
    <div sec:authorize="isAuthenticated()">
        <div class="box">
            Hello, <strong th:text="${#authentication.name}"></strong>!
        </div>
    </div>
    <div sec:authorize="isAnonymous()">
        <div class="box">
            <a class="button login is-primary" th:href="@{/oauth2/authorization/cognito}">
              Log in with Amazon Cognito</a>
        </div>
    </div>
</div>

📌 页面逻辑说明:

  • 如果已登录,显示欢迎信息
  • 如果未登录,显示一个“使用 Cognito 登录”的链接
  • 注意:链接中的 cognito 来自我们在配置文件中定义的客户端注册名称

最后,配置控制器将根路径映射到这个页面:

@Configuration
public class CognitoWebConfiguration implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}

5. 运行应用

编写主类启动应用:

@SpringBootApplication
public class SpringCognitoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringCognitoApplication.class, args);
    }
}

✅ 启动后访问 http://localhost:8080,点击登录链接,跳转至 Cognito 登录页面。输入之前创建的用户信息,即可看到欢迎信息。


6. 总结

本文介绍了如何将 Spring Security 与 Amazon Cognito 集成,实现基于 OAuth2 的登录流程。

整个过程只需要:

  • 在 Cognito 上完成基础配置
  • 添加两个依赖
  • 配置 application.yml
  • 编写简单的安全配置类和登录页面

整个过程简单高效,适合快速接入 AWS Cognito 认证体系。

优点总结:

  • 零代码实现认证流程
  • 易于与 Spring Boot 集成
  • 可轻松扩展支持多身份提供商

📌 常见踩坑点提醒:

  • Cognito 的回调 URL 与 Spring 配置必须完全一致
  • 用户池域名必须正确配置
  • Spring Security 的 .oauth2Login() 必须启用
  • 登录链接中的 cognito 必须与注册客户端名一致


原始标题:Spring Security with Amazon Cognito | Baeldung