I'm trying to make a very basic application to understand how Spring Boot Security works with JPA. This is my configuration file:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/index").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout.permitAll());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
return new MyDatabaseUserDetailsService();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
My User entity:
@Entity
@Table(name = "users")
public class MyUser {
@Id
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "authorities")
private String authorities;
public MyUser(String username, String password, String authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
public MyUser() {
}
// Getters and Setters
}
My UserDetails class:
public class MyUserDetails implements UserDetails {
private MyUser myUser;
public MyUserDetails(MyUser myUser) {
this.myUser = myUser;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(myUser.getAuthorities());
return Arrays.asList(authority);
}
@Override
public String getPassword() {
return myUser.getPassword();
}
@Override
public String getUsername() {
return myUser.getUsername();
}
}
And my UserDetailsService:
public class MyDatabaseUserDetailsService implements UserDetailsService{
@Autowired
UserDaoImpl userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MyUser user = userDao.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Could not find user");
}
return new MyUserDetails(user);
}
}
My problem is that when I run the application, I obtain the message: Using generated security password: 4f50cde6-c1ad-406e-9968-6e51b6b05bc0
This generated password is for development use only. Your security configuration must be updated before running your application in production.
and all my views are secured. I think there are two problems: 1- my configuration to permit the view /index doesn´t work 2- my users (from my database) doesn´t work and only works te user user/4f50cde6-c1ad-406e-9968-6e51b6b05bc0 that spring generates.
Maybe is something I don´t understand about security, but I don´t know what can be.
Thank you very much!
The problem was not in the security configuration. The problem was that, by having all the classes separated into packages, in the App class that launches the application, you must indicate all the packages in which Spring has to look for Beans. That is, you must add the annotations @ComponentScan, @EntityScan and @EnableJpaRepositories
@ComponentScan(basePackages = {"com.pgsanchez.ww2dates.controller",
"com.pgsanchez.ww2dates.dao",
"com.pgsanchez.ww2dates.securingweb",
"com.pgsanchez.ww2dates.service",
"com.pgsanchez.ww2dates"})
@EntityScan(basePackages= {"com.pgsanchez.ww2dates.model"}) //Packages donde tiene que buscar clases del modelo
@EnableJpaRepositories(basePackages= {"com.pgsanchez.ww2dates.dao"})
@SpringBootApplication
public class Ww2datesJpaApplication {
public static void main(String[] args) {
SpringApplication.run(Ww2datesJpaApplication.class, args);
}
}
An important thing is that, when the configuration is not correct, or when something is missing, as in this case, Spring activates security by default, which blocks all pages and tells you, in the console, the password with which you must access . That's why that message always appeared.