【问题标题】:Facebook Spring OAuth2User does not contain emailFacebook Spring OAuth2User 不包含电子邮件
【发布时间】:2019-10-10 09:01:55
【问题描述】:

我正在尝试使用 Spring OAuth2 在我的 Spring webapp 的 Facebook 上实现注册阶段。我正在关注本指南https://www.callicoder.com/spring-boot-security-oauth2-social-login-part-2/,但我的代码中的某些内容无法按预期工作。 OAuth2User 类型的对象在属性中只有 facebook 帐户的 id 和名称。

特别是在@Service 类中CustomOAuth2UserService 方法中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,但没有 email。

我的 CustomOAuth2UserService 类是这样的:

@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 类中插入:

@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);
       }
 }

【问题讨论】:

    标签: spring-boot spring-security spring-security-oauth2 spring-oauth2


    【解决方案1】:

    我找到了这个问题的解决方案。我需要在属性文件中指定我感兴趣的字段。 所以我需要在 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/,您可以自动生成包含您需要的所有字段的网址。拥有它后,您只需将其粘贴到此属性 spring.security.oauth2.client.provider.facebook.userInfoUri 旁边即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 1970-01-01
      • 2020-07-07
      • 2011-06-22
      • 1970-01-01
      相关资源
      最近更新 更多