У меня есть 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;
}
}
Я трачу на эту проблемуодну неделю, но я все еще не могу решить, пожалуйста, о помощи / подсказки :) С уважением