Problem in Spring Security
unknown
java
5 hours ago
6.1 kB
16
Indexable
// trying to implement basic username-password authentication in spring.. no JWT yet // application flow, as per my understanding: - FilterChain => AuthenticaionManager (ProviderManager) => accesses AuthenticationProvider (in my case, its DaoAuthenticationProvider) => accesses UserDetailsService (in this case, JdbcUserDetailsService) => accesses DataSource to connect to DB // conclusion reached by me: Create custom UserDetailsService, create custom User model; tell spring security to use these custom ones instead of its default values // 1. Created CustomUserDetailsService and its implemmentation // CustomUserDetailsService.java @Service public interface CustomUserDetailsService extends UserDetailsService{ public String create(String username, String password, String email); } // CustomUserDetailsServiceImpl.java @Component public class CustomUserDetailsService implements CustomUserDetailsService { @Autowired private CustomUserRepository userRepo; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return userRepo.findByUsername(username); } public String create(String username, String password, String email) { // Encodes the password and creates a new User object CustomUser u = new CustomUser(username, new BCryptPasswordEncoder().encode(password), email); u.setRole(List.of("USER")); // Saves the new user to the database userRepo.save(u); return "Create Successfully !"; } } // CustomUserRepository.java public interface CustomUserRepository extends JpaRepository<CustomUser, Long> { public UserDetails findByUsername(String username); } // 2. Created Custom User model // CustomUser.java @Entity public class CustomUser implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String username; private String email; private String password; private List<String> role; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return role.stream() .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) .collect(Collectors.toList()); } @Override public String getPassword() { // TODO Auto-generated method stub return null; } @Override public String getUsername() { // TODO Auto-generated method stub return null; } public void setPassword(String password) { this.password = password; } public List<String> getRole() { return role; } public void setRole(List<String> role) { this.role = role; } public CustomUser() { super(); // TODO Auto-generated constructor stub } public CustomUser(long id, String username, String email) { super(); this.id = id; this.username = username; this.email = email; } public CustomUser(String username, String email, String password) { super(); this.username = username; this.email = email; this.password = password; } } // 3. Telling Spring Security to use these custom objects instead of its own default config // WebSecurityConfig.java @Configuration @EnableWebSecurity public class WebSecurityConfig { @Autowired private CustomUserService customUserService; @Value("${spring.datasource.driver-class-name}") public String databaseDriverClassName; @Value("${spring.datasource.url}") public String databaseUrlName; @Value("${spring.datasource.username}") public String databaseUsername; @Value("${spring.datasource.password}") public String databasePassword; // 1. custom security filter chain for authorization and authentication paths @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/unauth/*").permitAll() .requestMatchers("/login/").permitAll() .anyRequest().denyAll() ) .httpBasic(Customizer.withDefaults()) .build(); } // 2. setup datasource to connect to database --> This is causing problem (the circular dependency error I mentioned) // @Bean // public DriverManagerDataSource dataSource() { // DriverManagerDataSource dataSource = new DriverManagerDataSource(); // dataSource.setDriverClassName(databaseDriverClassName); // dataSource.setUrl(databaseUrlName); // dataSource.setUsername(databaseUsername); // dataSource.setPassword(databasePassword); // System.out.println("datasource initialized"); // return dataSource; // } } // Here is complete error log // Description: // The dependencies of some of the beans in the application context form a cycle: // entityManagerFactory defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class] // ┌─────┐ // | dataSourceScriptDatabaseInitializer defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class] // ↑ ↓ // | webSecurityConfig (field private com.sample.springsecurity.service.CustomUserDetailsService com.sample.springsecurity.config.WebSecurityConfig.customUserDetailsService) // ↑ ↓ // | customUserDetailsServiceImpl (field private com.sample.springsecurity.repository.CustomUserRepository com.sample.springsecurity.serviceImpl.CustomUserDetailsServiceImpl.userRepo) // ↑ ↓ // | customUserRepository defined in com.sample.springsecurity.repository.CustomUserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration // ↑ ↓ // | jpaSharedEM_entityManagerFactory // └─────┘ // Action: // Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true. // What I cannot understand -> Where exactly is spring injecting this datasource bean? from what I have understood, it should only be injecting it inside the
Editor is loading...
Leave a Comment