October 2, 2024
Add Spring Security

Complete Application with Spring Boot – Part 3 (Add Spring Security)

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:

  1. Add the Dependencies
  2. Write the Methods for /login and /logout
  3. Add Test Records
  4. Set up User Model and Repository
  5. Implement UserDetailsService
  6. Implement UserDetails Interface
  7. 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

0 0 votes
Article Rating
Subscribe
Notify of
guest

7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Nirmalya roy
Nirmalya roy
4 years ago

I have created what u did but after login my page is not redirected to index page .

Abhilash
Abhilash
6 months ago

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

Abhilash
Abhilash
6 months ago

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

Last edited 6 months ago by Abhilash
Abhilash
Abhilash
6 months ago

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

Kindson
6 months ago
Reply to  Abhilash

This error is quite explanatory. You can see that the call to getPrincipal() returns null. You need to investigate that