我想从 Google 用户那里获取电子邮件地址。为此,我使用此依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
<version>3.0.4</version>
</dependency>
登录后,用户被重定向到此控制器:
@Controller
public class OAuthController {
@GetMapping("/google")
public ResponseEntity<String> google() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof OAuth2AuthenticationToken) {
OAuth2User user = (OAuth2User) authentication.getPrincipal();
String email = user.getAttribute("email");
System.out.println(email);
} else {
System.out.println("No Email");
}
return ResponseEntity.ok("Hello");
}
但是,我总是进入 else 语句。这是
authentication
的回归:
这是我的安全配置:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy());
http.authorizeHttpRequests(auth ->
auth
.requestMatchers("/api/welcome").authenticated()
.anyRequest().permitAll()
);
http.httpBasic();
http.logout().permitAll();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
http.oauth2Login(Customizer.withDefaults());
return http.build();
}
在 Google Cloud 的 OAuth 同意屏幕中,我添加了我的电子邮件地址作为测试用户,并添加了范围 .../auth/userinfo.email 和 .../auth/userinfo.profile。我的 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
登录时,Google 会突出显示电子邮件地址将被共享。参见:
那么为什么我看不到电子邮件地址?
OAuth2User
实际上应该是OidcUser
,它延伸了OAuth2User
和IdTokenClaimAccessor
。这意味着您应该能够执行以下操作:
@Controller
public class OAuthController {
@GetMapping("/google")
public ResponseEntity<String> google() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if ( authentication instanceof OAuth2AuthenticationToken oauth &&
oauth.getPrincipal() instanceof OidcUser oidcUser) {
System.out.println(oidcUser.getEmail());
} else {
System.out.println("No Email");
}
return ResponseEntity.ok("Hello");
}
}