I am developing an application using Spring Boot and Thymeleaf. I managed to integrate with the html pages.
The login and registration work, and after an user logs in he is redirected to the /homepage, but when after that when I try to go to another page (that requires authentication), I am redirected automatically to the login page, meaning the user session was not created?
I want the pages “/contact”, “/about”, “/homepage” to be available for authenticated users.
I will attach part of my code.
SecurityConfig.java
@Configuration @EnableWebSecurity @EnableMethodSecurity
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(){
return new AppUserDetailsService();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService());
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.securityContext(securityContext -> securityContext
.requireExplicitSave(false)
.securityContextRepository(new HttpSessionSecurityContextRepository()))
.authorizeHttpRequests(auth->auth
.requestMatchers(HttpMethod.GET, "/admin/all", "/admin/single").hasRole("ADMIN")
.requestMatchers(HttpMethod.GET, "/", "/login/**", "/register/**", "/login/check/**", "/images/**", "/about-me", "/contact-me", "/style/**", "/logout/**").permitAll()
.requestMatchers(HttpMethod.POST, "/register/save").permitAll()
.anyRequest().authenticated()
)
.sessionManagement((session) -> session
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.maximumSessions(2)
.maxSessionsPreventsLogin(true)
)
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login/check")
)
.logout(logout -> logout
.deleteCookies("JSESSIONID")
.logoutUrl("/logout")
.logoutSuccessUrl("/")
)
.httpBasic(Customizer.withDefaults())
;
return http.build();
}
}
FrontendController.java
@Controller
public class FrontendController {
@Autowired
UserRepo userRepo;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@GetMapping("/")
public String landing(Model model){
return "landing";
}
@GetMapping("/homepage")
public String homepage(Model model){
return "homepage";
}
@GetMapping("/register")
public String showRegister(Model model){
model.addAttribute("appUser", new AppUser());
return "register";
}
@PostMapping("/register/save")
public String register(AppUser appUser, Model model, HttpSession session) {
if(userRepo.findByEmail(appUser.getEmail()).isEmpty()){
appUser.setPassword(bCryptPasswordEncoder.encode(appUser.getPassword()));
userRepo.save(appUser);
model.addAttribute("name", appUser.getName());
model.addAttribute("image", appUser.getImage());
model.addAttribute("email", appUser.getEmail());
session.setAttribute("appUser", appUser);
return "homepage";
}
else return "register";
}
@GetMapping("/login")
public String login(Model model) {
model.addAttribute("result", "");
return "login";
}
@GetMapping("/login/check")
public String checkUser(@RequestParam("email") String email, @RequestParam("password") String password, Model model, HttpSession session) {
AppUser appUser = userRepo.findUserByEmail(email);
if(appUser != null){
String encodedPassword = userRepo.findPasswordByEmail(email);
if(bCryptPasswordEncoder.matches(password, encodedPassword)){
model.addAttribute("result", "true");
model.addAttribute("name", appUser.getName());
model.addAttribute("image", appUser.getImage());
model.addAttribute("email", appUser.getEmail());
session.setAttribute("appUser", appUser);
return "homepage";
}
else {
model.addAttribute("result", "false");
return "login";
}
}
return "login";
}
@GetMapping("/about")
public String about(){
return "about";
}
@GetMapping("/about-me")
public String aboutMe(){
return "about-me";
}
@GetMapping("/contact")
public String contact(){
return "contact";
}
@GetMapping("/contact-me")
public String contactMe(){
return "contact-me";
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.licenta</groupId>
<artifactId>v3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>DEMO</name>
<description>Demo project for Spring Boot - v3</description>
<properties>
<java.version>18</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Lavinia Smantana is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.