Spring Social-SimpleSocialUserDetailsS​​ervice和UserDetailsS​​ervice

时间:2018-10-28 12:40:19

标签: spring facebook spring-security social

我有2个班级: -UserDetailsS​​ervice -SimpleSocialUserDetailsS​​ervice 并且我想有两种选择来登录我的应用程序:普通登录/注册并通过Facebook。

我的自定义UserDetailsS​​ervice看起来如下:

@Service
@RequiredArgsConstructor
public class MyUserDetailsService implements UserDetailsService {

  private final UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByLogin(username);
    if(user == null) {
      throw new UsernameNotFoundException(username);
    }
    return new MyUserPrincipal(user);
  }
}

SimpleSocialUserDetailsS​​ervice类的外观如下:

@Service
@RequiredArgsConstructor
public class SimpleSocialUserDetailsService implements SocialUserDetailsService {

  private final UserDetailsService userDetailsService;

  @Override
  public SocialUserDetails loadUserByUserId(String userId)
      throws UsernameNotFoundException, DataAccessException {
    UserDetails userDetails = userDetailsService.loadUserByUsername(userId);
    return new SocialUser(
        userDetails.getUsername(),
        userDetails.getPassword(),
        userDetails.getAuthorities());
  }
}

在数据库中,我为普通用户和Facebook用户创建表。对于来自facebook的用户,我具有以下架构:

CREATE TABLE UserConnection (
    userId varchar(255) NOT NULL,
    providerId varchar(255) NOT NULL,
    providerUserId varchar(255),
    rank int NOT NULL,
    displayName varchar(255),
    profileUrl varchar(512),
    imageUrl varchar(512),
    accessToken varchar(255) NOT NULL,
    secret varchar(255),
    refreshToken varchar(255),
    expireTime bigint,
    PRIMARY KEY (userId, providerId, providerUserId));
CREATE UNIQUE INDEX UserConnectionRank
    ON UserConnection(userId, providerId, rank);

正常的登录/注册工作正常,我已经在开始时创建了此功能,但是我想通过Facebook获得第二选择。我调试了很多应用程序,问题出在类SimpleSocialUserDetailsS​​ervice中的这一行:

UserDetails userDetails = userDetailsService.loadUserByUsername(userId);

因为应用无法找到该用户,并且我得到了一个空值,但是在表UserConnection中该用户存在。

我的SocialConfig:

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

  @Autowired
  private DataSource dataSource;

  @Bean
  public ConnectController connectController(
      ConnectionFactoryLocator connectionFactoryLocator,
      ConnectionRepository connectionRepository) {
    return new ConnectController(connectionFactoryLocator, connectionRepository);
  }

  @Override
  public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer,
      Environment env) {
    connectionFactoryConfigurer.addConnectionFactory(new FacebookConnectionFactory(
        env.getProperty("spring.social.facebook.app-id"),
        env.getProperty("spring.social.facebook.app-secret")
    ));
  }

  @Override
  public UserIdSource getUserIdSource() {
    return new AuthenticationNameUserIdSource();
  }

  @Override
  public UsersConnectionRepository getUsersConnectionRepository(
      ConnectionFactoryLocator connectionFactoryLocator) {
    JdbcUsersConnectionRepository repository =
        new JdbcUsersConnectionRepository(
            dataSource,
            connectionFactoryLocator,
            Encryptors.noOpText());
    repository.setConnectionSignUp(
        new SecurityImplicitConnectionSignUp(userDetailsManager()));
    return repository;
  }

  @Bean
  public JdbcUserDetailsManager userDetailsManager() {
    JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
    manager.setDataSource(dataSource);
    manager.setEnableAuthorities(true);
    return manager;
  }
}

我的SecurityConfig:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private MyUserDetailsService userDetailsService;

  @Autowired
  private DataSource dataSource;

  @Override
  protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider());
  }

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth)
      throws Exception {
    auth
        .jdbcAuthentication()
        .dataSource(dataSource)
        .withDefaultSchema();
  }

  @Bean
  public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userDetailsService);
    authProvider.setPasswordEncoder(encoder());
    return authProvider;
  }

  @Bean
  public PasswordEncoder encoder() {
    return new BCryptPasswordEncoder(11);
  }

  @Bean
  public SimpleSocialUserDetailsService simpleSocialUserDetailsService() {
    return new SimpleSocialUserDetailsService(userDetailsService);
  }

  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http
        .csrf().disable()
          .headers().frameOptions().disable()
        .and()
          .authorizeRequests()
          .antMatchers("/login*", "/success*").anonymous()
          .antMatchers("/auth/**", "/signup/**", "/css/*", "/webjars/**","/js/*","/image/*").permitAll()
          .anyRequest().authenticated()
        .and()
          .formLogin().loginPage("/login")
          .successForwardUrl("/tasks")
        .and()
          .logout()
          .logoutUrl("/logout")
          .logoutSuccessUrl("/logout-success").permitAll()
        .and()
          .apply(new SpringSocialConfigurer());
  }
}

针对新用户的我的SecurityImplictConnectionSignUp看起来像这样:

@RequiredArgsConstructor
public class SecurityImplicitConnectionSignUp implements ConnectionSignUp {

  public final UserDetailsManager userDetailsManager;

  @Override
  public String execute(Connection<?> connection) {
    String providerUserId = connection.getKey().getProviderUserId();
    User newUser = new User(
        providerUserId, "", Arrays.asList(new SimpleGrantedAuthority("USER")));
    userDetailsManager.createUser(newUser);
    return providerUserId;
  }
}

我花了一个星期解决这个问题,但仍然无法解决,请提供帮助/提示:) 问候

0 个答案:

没有答案