OAuth登录后无法获取Google用户邮箱地址问题排查
问题描述
使用spring-boot-starter-oauth2-client(3.0.4版本)集成Google OAuth2登录,登录后重定向到自定义的OAuthController,但控制器中判断Authentication实例类型时始终进入else分支,无法获取用户邮箱。已配置Google Cloud授权屏幕的测试用户及.../auth/userinfo.email、.../auth/userinfo.profile权限,application.yml也声明了email和profile Scope,登录时Google提示会共享邮箱,但仍无法获取。
核心问题与修复方案
1. YAML配置缩进错误(Scope未归属Google客户端)
你的application.yml中scope配置缩进错误,它应该属于google节点下,而非与google同级。错误的缩进导致Scope并未被正确应用到Google OAuth2客户端,Google因此不会返回邮箱信息。
修复后的application.yml:
spring: security: oauth2: client: registration: google: client-id: <my-client-id> client-secret: <my-client-secret> redirect-uri: http://localhost:8080/google scope: - email - profile
2. 自定义Redirect URI未关联OAuth2登录流程
Spring Security OAuth2默认的回调路径是/login/oauth2/code/google,如果你自定义了redirect-uri为http://localhost:8080/google,需要确保该路径被纳入OAuth2登录的回调处理逻辑,否则登录后的认证信息不会被正确存入SecurityContext。
建议先改用默认回调路径测试,修改application.yml:
redirect-uri: "{baseUrl}/login/oauth2/code/google"
同时调整Security配置,指定登录成功后的跳转路径:
http.oauth2Login(oauth2 -> oauth2 .defaultSuccessUrl("/google", true) // 登录成功后跳转到/google );
3. JWT过滤器干扰OAuth2认证信息
你的Security配置中添加了jwtFilter在UsernamePasswordAuthenticationFilter之前,这个过滤器可能会覆盖或清除OAuth2登录后生成的OAuth2AuthenticationToken,导致SecurityContext中不是预期的认证类型。
如果当前不需要JWT认证,可暂时移除http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);测试;如果必须保留,需要调整过滤器的执行顺序或逻辑,确保OAuth2的认证信息不会被覆盖。
4. 控制器认证信息获取方式优化
可以直接在控制器方法参数中注入OAuth2AuthenticationToken,Spring会自动绑定,避免手动从SecurityContext获取可能出现的上下文问题:
修改后的控制器代码:
@Controller public class OAuthController { @GetMapping("/google") public ResponseEntity<String> google(OAuth2AuthenticationToken authentication) { if (authentication != null) { OAuth2User user = authentication.getPrincipal(); String email = user.getAttribute("email"); System.out.println(email); } else { System.out.println("No Email"); } return ResponseEntity.ok("Hello"); } }
验证步骤
- 修复YAML缩进后,重启应用
- 访问Google登录入口(默认路径为
/oauth2/authorization/google) - 登录后检查控制台是否输出邮箱信息
内容的提问来源于stack exchange,提问作者xRay

