In this part, we would add Spring Security to our application. You can find Part 1 and 2 below.
Part 1 – Getting Started and Setting up the Pages
Part 2 – Showing Images and Thumbnails
With Spring security we would allows users to login to the application using their username and password. As usual, we would take it step by step. I also recommend you follow the video lessons as well.
To add Spring Security, we would follow these 7 steps:
- Add the Dependencies
- Write the Methods for /login and /logout
- Add Test Records
- Set up User Model and Repository
- Implement UserDetailsService
- Implement UserDetails Interface
- Extend the WebSecurityConfigurerAdapter
Step 1 – Add the dependencies
You need to add the following two dependencies to enable spring security.
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Step 2 – Write the method for /login and /logout
In the ApplicationController file, write a method to return the login page. The url mapping would be “/login”.
Do the same for /logout
Step 3 – Add test records
For now, we would just manually add some records to MySQL database. So open MySQL command prompt and add two some records to the user table.
(See the video for the procedure)
Step 4 – Setup the User Model and Repository
Check the the user model has the fields: id, username and password.
In the repository write a method to find user by username
Step 5 – Implement the UserDetailsService
Create a class in the Services package and call it MyUserDetailsService. This class should implement UserDetailsService.
Add the @Service annotation to this class.
In the loadUserByUsername method, create a new user using the repository’s findByUsername method.
Then instantiate an return a new UserPrincipal object using the user as an argument (watch the video)
Step 6 – Implement the UserDetails Interfaces
In the models package, create a class UserPrincipal that implements UserDetails interface.
In this class create a private member variable of type User. Then generate the constructor.
The modify the getUsername and getPassword to return user.getUsername and user.getPassword
Also set the methods in this class to return true.
Modify the getAuthorities method (see the video)
Step 7: Extend the WebSecurityConfiurerAdapter
Create the AppSecurityConfig file to extend the WebSecurityConfigurerAdapter class.
Add the @Configuration and @EnableWebSecurity to this class
Then override the configure method.
Create the PasswordEncoder bean and other methods.
Autowire the UserDetailsService
Then create a bean to return a DaoAuthenticationProvider
The final content of this file is given below:
@Configuration @EnableWebSecurity public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers( "/login", "/resources/**", "/css/**", "/fonts/**", "/img/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login").permitAll() .and() .logout().invalidateHttpSession(true) .clearAuthentication(true) .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/login").permitAll(); } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } @Autowired private UserDetailsService userDetailsService; @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(passwordEncoder()); return provider; } }
I recommend you watch the video for clarification. See video below
I have created what u did but after login my page is not redirected to index page .
I have created what u did but after login my page is not redirected to index page. Tried different way but not working. What is he mistake or what needs to be change. Please update
Make sure you have this in the AppSecurityConfig.java
.defaultSuccessUrl(“/index”, true)
Also make sure the controller method exists in the SecurityController.java
@RequestMapping(“/index”)
public String homePage() {
return “index”;
}
Its still not working.
this is my ApplicationSecurityConfig.java page. I have updates few things since few things got deprecated. Please check if there is any correction needed and let me know.
@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig{
@Bean
public SecurityFilterChain securityfilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers(“/login”, “/resources/**”, “/css/**”, “/fonts/**”, “/img/**”).permitAll()
.anyRequest().authenticated()
)
.formLogin(login -> login
.loginPage(“/login”).permitAll()
.defaultSuccessUrl(“/index”, true)
)
.logout(logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher(“/logout”))
.logoutSuccessUrl(“/login”).permitAll()
.invalidateHttpSession(true)
.clearAuthentication(true)
);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Autowired
private UserDetailsService userDetailsService;
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
}
rest all the files are exactly coded as you have shown in the video. Only ApplicationSecurityConfig was changed a bit. I’m not able to catch where is the error. The login page is not logging in after giving username and password
What page does it redirect to after you login?
hii. I have solved this error. thankyou.
now after proceeding to video 38. after applying the changes it gives whitelabel error and error with authentication.
<!– user login dropdown start–>
<li class=“dropdown”>
<a data-toggle=“dropdown” class=“dropdown-toggle” th:href=“@{‘/img/photos/’ + ${#authentication.getPrincipal().getUsername()} +’.jpg’}”>
<span class=“profile-ava”>
<img alt=“” th:src=“@{‘/img/photos/’ + ${#authentication.getPrincipal().getUsername()} +’.jpg’}” height=“38” width=“38”>
</span>
<span class=“username” th:text=“${#authentication.getPrincipal().getUsername()}”>Guest</span>
<b class=“caret”></b>
</a>
<ul class=“dropdown-menu extended logout”>
<div class=“log-arrow-up”></div>
<li class=“eborder-top”>
<a th:href=“@{/profile}”><i class=“icon_profile”></i> My Profile</a>
</li>
<li>
<a href=“#”><i class=“icon_mail_alt”></i> My Inbox</a>
</li>
<li>
<a href=“#”><i class=“icon_clock_alt”></i> Timeline</a>
</li>
<li>
<a href=“#”><i class=“icon_chat_alt”></i> Chats</a>
</li>
<li>
<a th:href=“@{/logout}”><i class=“icon_key_alt”></i> Log Out</a>
</li>
<li>
<a href=“#”><i class=“icon_key_alt”></i> Documentation</a>
</li>
<li>
<a href=“#”><i class=“icon_key_alt”></i> Documentation</a>
</li>
</ul>
</li>
<!– user login dropdown end –>
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: “#authentication.getPrincipal().getUsername()” (template: “index” – line 275, col 63)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method getPrincipal() on null context object
these are the error
This error is quite explanatory. You can see that the call to getPrincipal() returns null. You need to investigate that