Spring Boot OAuth2资源服务中自动获取用户信息(姓名、邮箱)方案
Spring Boot + Cognito:自动获取用户信息(含缓存)
你不需要硬编码调用UserInfo端点,Spring Security OAuth2提供了内置机制来自动获取并缓存用户信息,以下是两种可行方案:
方案一:自动调用UserInfo端点获取用户信息
Spring Security的OidcUserService(针对OIDC协议,Cognito原生支持)可以自动调用UserInfo端点,并结合Spring Cache实现缓存管理,避免重复请求。
1. 配置application.yml
添加Cognito的核心配置,无需在代码中硬编码端点地址:
spring: security: oauth2: resourceserver: jwt: issuer-uri: https://cognito-idp.${region}.amazonaws.com/${user-pool-id} userinfo: uri: https://${user-pool-domain}.auth.${region}.amazoncognito.com/oauth2/userinfo client-id: ${your-resource-server-client-id}
issuer-uri:用于验证JWT签名与有效性,必须和Cognito用户池的 issuer 地址一致userinfo.uri:Cognito官方提供的UserInfo端点地址,通过配置变量动态注入client-id:你在Cognito中创建的资源服务器客户端ID
2. 配置SecurityConfig(含缓存)
启用Spring Cache,并配置带缓存的OIDC用户服务:
@Configuration @EnableCaching public class JWTSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http, OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService) throws Exception { http.authorizeRequests(authz -> authz .antMatchers(HttpMethod.GET, "/foos/**").hasAuthority("SCOPE_read") .antMatchers(HttpMethod.POST, "/foos").hasAuthority("SCOPE_write") .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())) .oidcUserService(oidcUserService)); // 绑定自动获取UserInfo的服务 return http.build(); } // 自定义JWT转换逻辑,合并权限信息 private JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(new JwtGrantedAuthoritiesConverter()); return converter; } // 封装带缓存的OIDC用户服务 @Bean public OAuth2UserService<OidcUserRequest, OidcUser> cachedOidcUserService(CacheManager cacheManager) { DefaultOidcUserService delegate = new DefaultOidcUserService(); // 使用Spring Cache缓存用户信息,缓存名称为userInfoCache return new CachingOAuth2UserService<>(delegate, cacheManager.getCache("userInfoCache")); } // 配置缓存管理器(示例用Caffeine实现) @Bean public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager("userInfoCache"); // 缓存有效期与Cognito Access Token默认有效期匹配(1小时) cacheManager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.HOURS) .maximumSize(1000)); return cacheManager; } }
CachingOAuth2UserService是Spring内置组件,自动缓存UserInfo响应,同一用户的重复请求会直接读取缓存- 缓存参数可根据业务需求调整有效期和容量
3. 在业务代码中获取用户信息
通过SecurityContextHolder直接获取认证后的用户属性:
@RestController public class FooController { @GetMapping("/foos/me") public Map<String, Object> getCurrentUser() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof OidcUser oidcUser) { return Map.of( "姓名", oidcUser.getFullName(), "邮箱", oidcUser.getEmail(), "用户ID", oidcUser.getSubject() ); } return Collections.emptyMap(); } }
方案二:解析ID Token获取用户信息
如果前端能将ID Token传递到后端(比如放在Authorization头中),可以直接解析ID Token获取用户信息,无需调用UserInfo端点——ID Token本身就包含name、email等基础用户属性。
1. 基础Security配置
ID Token本质是JWT,Spring Security可直接验证解析:
@Configuration public class JWTSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeRequests(authz -> authz .antMatchers(HttpMethod.GET, "/foos/**").hasAuthority("SCOPE_read") .antMatchers(HttpMethod.POST, "/foos").hasAuthority("SCOPE_write") .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt()); return http.build(); } }
只需确保application.yml中的issuer-uri配置正确,Spring会自动验证ID Token的签名、有效期与受众。
2. 从ID Token提取用户信息
@GetMapping("/foos/me") public Map<String, Object> getCurrentUser() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof Jwt jwt) { return Map.of( "姓名", jwt.getClaimAsString("name"), "邮箱", jwt.getClaimAsString("email"), "用户ID", jwt.getClaimAsString("sub") ); } return Collections.emptyMap(); }
注意事项
- 确保Cognito用户池已启用OIDC功能,资源服务器客户端的权限配置正确
- 使用ID Token方案时,需前端配合传递ID Token,同时注意ID Token的有效期(Cognito默认1小时)
- 缓存配置可根据业务场景调整,比如针对高频访问用户延长缓存时间
内容的提问来源于stack exchange,提问作者Miletos
相关产品推荐
相关产品推荐

