Facebook Spring OAuth2User 不包含电子邮件
Facebook Spring OAuth2User does not contain email
我正在尝试使用 Spring OAuth2 在我的 Spring 网络应用程序的 Facebook 上实施注册阶段。我正在按照本指南 https://www.callicoder.com/spring-boot-security-oauth2-social-login-part-2/ 进行操作,但我的代码中的某些内容无法按预期工作。 OAuth2User 类型的对象在属性中只有 id 和 facebook 帐户的名称。
特别是@Service里面classCustomOAuth2UserService里面的方法processOAuth2User
private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) {
OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
if(StringUtils.isEmpty(oAuth2UserInfo.getEmail())) {
throw new OAuth2AuthenticationProcessingException("Email not found from OAuth2 provider");
}
...
}
oAuth2User.getAttributes(),正如我所说,只有两个属性:id 和 name 但没有电子邮件。
我的 CustomOAuth2UserService class 是这样的:
@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Autowired
private UserService userService;
@Override
public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest);
try {
return processOAuth2User(oAuth2UserRequest, oAuth2User);
} catch (AuthenticationException ex) {
throw ex;
} catch (Exception ex) {
// Throwing an instance of AuthenticationException will trigger the OAuth2AuthenticationFailureHandler
throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause());
}
}
private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) {
OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
if(StringUtils.isEmpty(oAuth2UserInfo.getId())) {
throw new RuntimeException("Id not found from OAuth2 provider");
}
FacebookUser user = null;
try {
user = (FacebookUser) userService.getByFacebookId(oAuth2UserInfo.getId());
} catch (UserNotFoundException e) {
user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo);
}
return new CustomUserDetails(user);
}
private FacebookUser registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) {
FacebookUser user = new FacebookUser(oAuth2UserInfo.getId());
user.setProvider(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()));
user.setIdentity(new Identity(oAuth2UserInfo.getName()));
user.setEmail(oAuth2UserInfo.getEmail());
return (FacebookUser) userService.addFacebookUser(user);
}
}
在SecurityConfiguration中插入class:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomOAuth2UserService customOAuth2UserService;
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.and()
.oauth2Login()
.loginPage("/login")
.userInfoEndpoint()
.userService(customOAuth2UserService);
}
}
我找到了这个问题的解决方案。我需要在属性文件中指定我感兴趣的字段。
所以我需要在 application.properties 文件中添加以下属性:
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri = https://www.facebook.com/v3.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri = https://graph.facebook.com/v3.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri = https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture
所以我的 application.properties 文件,关于 OAuth2 模块的内容是这样的:
spring.security.oauth2.client.registration.facebook.client-id=****
spring.security.oauth2.client.registration.facebook.client-secret=****
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri = https://www.facebook.com/v3.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri = https://graph.facebook.com/v3.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri = https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture
使用此在线工具https://developers.facebook.com/tools/explorer/,您可以自动生成包含您需要的所有字段的url。获得它后,只需将其粘贴到此 属性 spring.security.oauth2.client.provider.facebook.userInfoUri 旁边即可。
我正在尝试使用 Spring OAuth2 在我的 Spring 网络应用程序的 Facebook 上实施注册阶段。我正在按照本指南 https://www.callicoder.com/spring-boot-security-oauth2-social-login-part-2/ 进行操作,但我的代码中的某些内容无法按预期工作。 OAuth2User 类型的对象在属性中只有 id 和 facebook 帐户的名称。
特别是@Service里面classCustomOAuth2UserService里面的方法processOAuth2User
private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) {
OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
if(StringUtils.isEmpty(oAuth2UserInfo.getEmail())) {
throw new OAuth2AuthenticationProcessingException("Email not found from OAuth2 provider");
}
...
}
oAuth2User.getAttributes(),正如我所说,只有两个属性:id 和 name 但没有电子邮件。
我的 CustomOAuth2UserService class 是这样的:
@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Autowired
private UserService userService;
@Override
public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest);
try {
return processOAuth2User(oAuth2UserRequest, oAuth2User);
} catch (AuthenticationException ex) {
throw ex;
} catch (Exception ex) {
// Throwing an instance of AuthenticationException will trigger the OAuth2AuthenticationFailureHandler
throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause());
}
}
private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) {
OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
if(StringUtils.isEmpty(oAuth2UserInfo.getId())) {
throw new RuntimeException("Id not found from OAuth2 provider");
}
FacebookUser user = null;
try {
user = (FacebookUser) userService.getByFacebookId(oAuth2UserInfo.getId());
} catch (UserNotFoundException e) {
user = registerNewUser(oAuth2UserRequest, oAuth2UserInfo);
}
return new CustomUserDetails(user);
}
private FacebookUser registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) {
FacebookUser user = new FacebookUser(oAuth2UserInfo.getId());
user.setProvider(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()));
user.setIdentity(new Identity(oAuth2UserInfo.getName()));
user.setEmail(oAuth2UserInfo.getEmail());
return (FacebookUser) userService.addFacebookUser(user);
}
}
在SecurityConfiguration中插入class:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomOAuth2UserService customOAuth2UserService;
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.and()
.oauth2Login()
.loginPage("/login")
.userInfoEndpoint()
.userService(customOAuth2UserService);
}
}
我找到了这个问题的解决方案。我需要在属性文件中指定我感兴趣的字段。 所以我需要在 application.properties 文件中添加以下属性:
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri = https://www.facebook.com/v3.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri = https://graph.facebook.com/v3.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri = https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture
所以我的 application.properties 文件,关于 OAuth2 模块的内容是这样的:
spring.security.oauth2.client.registration.facebook.client-id=****
spring.security.oauth2.client.registration.facebook.client-secret=****
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri = https://www.facebook.com/v3.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri = https://graph.facebook.com/v3.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri = https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture
使用此在线工具https://developers.facebook.com/tools/explorer/,您可以自动生成包含您需要的所有字段的url。获得它后,只需将其粘贴到此 属性 spring.security.oauth2.client.provider.facebook.userInfoUri 旁边即可。