Spring Social - SimpleSocialUserDetailsService и UserDetailsService - PullRequest
0 голосов
/ 28 октября 2018

У меня есть 2 класса: - UserDetailsService - SimpleSocialUserDetailsService, и я хочу иметь 2 варианта входа в мое приложение: обычный вход в систему / регистрация и через facebook.

Мой пользовательский UserDetailsService выглядит так:

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

Класс SimpleSocialUserDetailsService выглядит так:

@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 были вторые опции.Я много отлаживаю свое приложение, и проблема с этой строкой в ​​классе SimpleSocialUserDetailsService:

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

Я трачу на эту проблемуодну неделю, но я все еще не могу решить, пожалуйста, о помощи / подсказки :) С уважением

...