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

Spring Reactive OAuth2资源服务器:将令牌声明与Cognito用户信息整合进Authentication

在Reactive Spring Security中整合Cognito令牌与用户额外信息

完全可以通过自定义JWT认证转换器的方式,在令牌验证阶段自动获取Cognito的用户额外信息,将其整合到自定义User对象并注入Authentication中,替代手动调用userInfo接口的方式。具体实现步骤如下:

1. 定义自定义用户对象

创建实现UserDetails的自定义用户类,用来承载令牌声明和额外获取的用户信息:

public class CustomUser implements UserDetails {
    private String username;
    private String email;
    private String avatar;
    private Collection<? extends GrantedAuthority> authorities;

    // 构造器、Getter/Setter
    @Override
    public boolean isAccountNonExpired() { return true; }
    @Override
    public boolean isAccountNonLocked() { return true; }
    @Override
    public boolean isCredentialsNonExpired() { return true; }
    @Override
    public boolean isEnabled() { return true; }
}

2. 实现Cognito用户信息获取服务

封装调用Cognito userInfo接口的逻辑:

@Service
public class CognitoUserInfoService {
    private final WebClient webClient;

    public CognitoUserInfoService(@Value("${cognito.user-info-uri}") String userInfoUri) {
        this.webClient = WebClient.builder().baseUrl(userInfoUri).build();
    }

    public Mono<CognitoUserInfo> fetchUserInfo(String accessToken) {
        return webClient.get()
                .headers(headers -> headers.setBearerAuth(accessToken))
                .retrieve()
                .bodyToMono(CognitoUserInfo.class);
    }

    // 内部类接收Cognito返回的用户信息
    public static class CognitoUserInfo {
        private String email;
        private String picture; // 对应头像字段
        // Getter/Setter
    }
}

注意:在配置文件中添加cognito.user-info-uri=https://my-congito-pool.auth.us-east-1.amazoncognito.com/oauth2/userInfo。

3. 自定义JWT认证转换器

实现Converter<Jwt, Mono<Authentication>>,在转换JWT令牌时自动调用用户信息服务,组装自定义用户对象:

@Component
public class CustomJwtAuthenticationConverter implements Converter<Jwt, Mono<Authentication>> {
    private final CognitoUserInfoService userInfoService;
    private final JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter();

    public CustomJwtAuthenticationConverter(CognitoUserInfoService userInfoService) {
        this.userInfoService = userInfoService;
    }

    @Override
    public Mono<Authentication> convert(Jwt jwt) {
        // 从JWT中提取权限信息
        Collection<GrantedAuthority> authorities = authoritiesConverter.convert(jwt);
        // 获取原始访问令牌
        String accessToken = jwt.getTokenValue();

        // 调用Cognito获取额外用户信息,组装自定义User并生成Authentication
        return userInfoService.fetchUserInfo(accessToken)
                .map(userInfo -> {
                    CustomUser customUser = new CustomUser();
                    customUser.setUsername(jwt.getSubject());
                    customUser.setEmail(userInfo.getEmail());
                    customUser.setAvatar(userInfo.getPicture());
                    customUser.setAuthorities(authorities);
                    return new UsernamePasswordAuthenticationToken(customUser, jwt, authorities);
                });
    }
}

4. 配置Reactive Security链

将自定义转换器注入到OAuth2资源服务器配置中:

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    private final CustomJwtAuthenticationConverter customJwtAuthenticationConverter;

    public SecurityConfig(CustomJwtAuthenticationConverter customJwtAuthenticationConverter) {
        this.customJwtAuthenticationConverter = customJwtAuthenticationConverter;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange(exchanges -> exchanges
                        .anyExchange().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwtAuthenticationConverter(customJwtAuthenticationConverter)
                        )
                );
        return http.build();
    }
}

优化建议

  • 添加缓存:对fetchUserInfo方法添加缓存(比如用@Cacheable或Reactor的cache()操作),避免每次请求都调用Cognito接口,减少延迟和开销。
  • 异常处理:在转换器中添加异常处理逻辑,比如调用userInfo接口失败时,可降级使用JWT中已有的信息,避免认证流程中断。
  • 权限自定义:如果需要自定义权限转换逻辑,可以扩展JwtGrantedAuthoritiesConverter或直接在转换器中手动生成权限集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:45:34