在Spring Boot控制器中获取Firebase认证Token的UID
Spring Boot中从Firebase JWT Token获取UID的最优方案
核心思路
利用Spring Security OAuth2 Resource Server的JWT认证机制,将Token中的UID自动绑定到请求上下文,通过注解直接在Controller中获取,无需手动解析请求头或传递不安全的查询参数。
步骤1:配置JWT认证转换器
修改SecurityConfig,自定义JwtAuthenticationConverter,将Firebase Token中的UID提取为认证主体(Principal),方便后续在接口中直接获取。Firebase ID Token的UID默认存储在sub字段中,若你的Token使用user_id字段,可自行替换。
@Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http.cors().and().csrf().disable() .authorizeHttpRequests { auth -> auth.antMatchers("/appauth/**").authenticated() } .oauth2ResourceServer { oauth2 -> oauth2.jwt { jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()) } } return http.build() } private fun jwtAuthenticationConverter(): JwtAuthenticationConverter { val converter = JwtAuthenticationConverter() // 可选:配置权限提取规则(如果需要基于Token的权限控制) val authoritiesConverter = JwtGrantedAuthoritiesConverter() authoritiesConverter.setAuthorityPrefix("ROLE_") converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter) // 提取UID作为认证主体 converter.setPrincipalExtractor { jwt: Jwt -> // Firebase Token的UID对应sub字段,根据实际Token结构调整 jwt.subject } return converter } }
步骤2:在Controller中直接获取UID
使用@AuthenticationPrincipal注解,直接将认证后的UID注入到接口方法参数中,无需任何额外解析操作:
@GetMapping(path = ["/projects"]) fun getProjects(@AuthenticationPrincipal uid: String): String { val user = someRepository.getUserByUid(uid) return user.projects }
进阶:自定义用户主体(可选)
如果需要从Token中提取更多用户信息(如邮箱、角色等),可以封装一个自定义的UserPrincipal类,让代码更具可读性:
1. 定义UserPrincipal类
data class UserPrincipal( val uid: String, // 可添加其他字段,如email、displayName等,从Jwt claims中提取 val email: String? = null ) : Principal { override fun getName(): String = uid }
2. 更新转换器的PrincipalExtractor
private fun jwtAuthenticationConverter(): JwtAuthenticationConverter { val converter = JwtAuthenticationConverter() // 权限配置保持不变 val authoritiesConverter = JwtGrantedAuthoritiesConverter() authoritiesConverter.setAuthorityPrefix("ROLE_") converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter) // 提取多个字段封装为UserPrincipal converter.setPrincipalExtractor { jwt: Jwt -> UserPrincipal( uid = jwt.subject, email = jwt.claims["email"]?.toString() ) } return converter }
3. Controller中使用自定义主体
@GetMapping(path = ["/projects"]) fun getProjects(@AuthenticationPrincipal userPrincipal: UserPrincipal): String { val user = someRepository.getUserByUid(userPrincipal.uid) return user.projects }
优势说明
- 安全可靠:避免了手动解析Token的出错风险,也杜绝了将UID作为查询参数传递的安全隐患。
- 代码简洁:无需重复编写Token解析逻辑,直接通过注解获取关键信息,降低冗余代码。
- 扩展性强:后续如需提取Token中其他字段,只需修改转换器和自定义主体即可,无需改动Controller逻辑。
内容的提问来源于stack exchange,提问作者Jemil Riahi
相关产品推荐
相关产品推荐

