简体   繁体   English

Spring Security-存储库SocialUser

[英]Spring Security - Repository SocialUser

My problem is to get log in my web application with facebook. 我的问题是使用Facebook登录我的Web应用程序。 Normal login/register works fine but when it comes by social provider i have a problem, below are my importants files along others: 正常的登录/注册工作正常,但是当社交提供程序出现问题时,以下是我的重要文件:

SecurityConfig.java 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 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 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;
}

SimpleSocialUserDetailsService.java 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());
  }
}

MyUserDetailsService.java 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 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 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 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();
  }
}

I got error like this: 我有这样的错误:

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

The problem is in your repository: 问题出在您的存储库中:

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

1) If you use Spring Data and your class is extended from JpaRepository , you don't have to add @Repository annotation on your class. 1)如果使用Spring Data并且您的类是从JpaRepository扩展的,则不必在类上添加@Repository批注。

2) In your method 2)用你的方法

SocialUser findByUsername(String username);

you return SocialUser , which is a class from Spring Social module and this class is not managed by JPA (that's why you receive an error). 您返回SocialUser ,这是Spring Social模块中的一个类,并且该类不受JPA管理(这就是为什么会收到错误)。 You should use either entity or Spring Data projection as a returned type in the method of your repository. 您应该使用实体或Spring Data投影作为存储库方法中的返回类型。

Let's assume that you have Users entity which should be something like: 假设您具有Users实体,该实体应类似于:

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

You can rewrite your method in the following way: 您可以通过以下方式重写您的方法:

Users findByUsername(String username);

Then you can convert entity / projection to SocialUser in your service: 然后,您可以在服务SocialUser实体/投影转换为SocialUser

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM