我的问题是使用 facebook 登录我的网络应用程序。正常的登录/注册工作正常,但当它来自社​​交提供商时,我遇到了问题,以下是我的重要文件和其他文件:

SecurityConfig.java

package pl.java.learning.todolist.infrastructure.config; 
 
@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
 
  @Autowired 
  private MyUserDetailsService userDetailsService; 
 
  @Autowired 
  private DataSource dataSource; 
 
  @Autowired 
  private UserSocialService userSocialService; 
 
  @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); 
  } 
 
  @Override 
  protected MyUserDetailsService userDetailsService() { 
    return userDetailsService; 
  } 
 
  @Bean 
  public SimpleSocialUserDetailsService simpleSocialUserDetailsService() { 
    return new SimpleSocialUserDetailsService(userDetailsService, userSocialService); 
  } 
 
  @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()); 
  } 
} 

SocialConfig.java

package pl.java.learning.todolist.infrastructure.config; 
 
@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; 
  } 
} 

CustomSocialUser.java

package pl.java.learning.todolist.domain.social; 
 
import java.util.Collection; 
import java.util.List; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
import lombok.AllArgsConstructor; 
import lombok.Data; 
import lombok.EqualsAndHashCode; 
import lombok.NoArgsConstructor; 
import lombok.ToString; 
import org.springframework.security.core.GrantedAuthority; 
import pl.java.learning.todolist.infrastructure.persistence.BaseEntity; 
 
@Data 
@Entity 
@AllArgsConstructor 
@NoArgsConstructor 
@EqualsAndHashCode(callSuper = true) 
@ToString 
@Table(name = "users") 
public class CustomSocialUser extends BaseEntity { 
  private String username; 
  private String password; 
  private Collection<? extends GrantedAuthority> authorities; 
} 

SimpleSocialUserDetailsS​​ervice.java

@Service 
@RequiredArgsConstructor 
public class SimpleSocialUserDetailsService implements SocialUserDetailsService { 
 
  private final UserDetailsService userDetailsService; 
  private final UserSocialService userSocialService; 
 
  @Override 
  public SocialUserDetails loadUserByUserId(String userId) 
      throws UsernameNotFoundException, DataAccessException { 
    CustomSocialUser customSocialUser = userSocialService.findByUsername(userId); 
    return new SocialUser( 
        customSocialUser.getUsername(), 
        customSocialUser.getPassword(), 
        customSocialUser.getAuthorities()); 
  } 
} 

MyUserDetailsS​​ervice.java

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

SecurityImplicitConnectionSignUp.java

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

UserSocialRepository.java

public interface UserSocialRepository extends JpaRepository<CustomSocialUser, Long> { 
  @Query("SELECT u FROM Users u WHERE u.username = ?1") 
  CustomSocialUser findByUsername(String username); 
} 

MyUserPrincipal.java

@RequiredArgsConstructor 
public class MyUserPrincipal implements UserDetails { 
 
  private final User user; 
 
  @Override 
  public Collection<? extends GrantedAuthority> getAuthorities() { 
    return user.getRoles(); 
  } 
 
  public Long getUserId() { 
    return user.getId(); 
  } 
 
  @Override 
  public String getPassword() { 
    return user.getPassword(); 
  } 
 
  @Override 
  public String getUsername() { 
    return user.getLogin(); 
  } 
 
  @Override 
  public boolean isAccountNonExpired() { 
    return true; 
  } 
 
  @Override 
  public boolean isAccountNonLocked() { 
    return true; 
  } 
 
  @Override 
  public boolean isCredentialsNonExpired() { 
    return true; 
  } 
 
  @Override 
  public boolean isEnabled() { 
    return user.getEnabled(); 
  } 
} 

我遇到这样的错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table: users, for columns: [org.hibernate.mapping.Column(authorities)] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:859) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) 
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) 
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) 
    at pl.java.learning.todolist.TodoListApplication.main(TodoListApplication.java:10) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table: users, for columns: [org.hibernate.mapping.Column(authorities)] 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:402) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) 
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) 
    ... 21 common frames omitted 
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table: users, for columns: [org.hibernate.mapping.Column(authorities)] 
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:456) 
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:423) 
    at org.hibernate.mapping.Property.isValid(Property.java:226) 
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597) 
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265) 
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329) 
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:461) 
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892) 
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) 
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) 
    ... 25 common frames omitted 

请您参考如下方法:

问题出在您的存储库中:

@Repository 
public interface UserSocialRepository extends JpaRepository<SocialUser, Long> { 
  @Query("SELECT u FROM Users u WHERE u.username = ?1") 
  SocialUser findByUsername(String username); 
} 

1) 如果您使用 Spring Data 并且您的类是从 JpaRepository 扩展的,则不必在您的类上添加 @Repository 注解。

2)在你的方法中

SocialUser findByUsername(String username); 

您返回SocialUser,它是Spring Social模块中的一个类,并且该类不是由JPA管理的(这就是您收到错误的原因)。您应该使用实体或 Spring Data 投影作为存储库方法中的返回类型。

假设您有 Users 实体,应该类似于:

@Entity 
@Table(name = "users") 
public class Users { 
    private String username; 
    // ... 
} 

您可以按以下方式重写您的方法:

Users findByUsername(String username); 

然后您可以将实体/投影转换为服务中的 SocialUser:

public UserDetails findByUsername(String username) { 
    Users user = userSocialRepository.findByUsername(username); 
    return new SocialUser(user.getUsername(), ...); 
} 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!