Code ví dụ Spring Boot remember me (Tự động login)

Code ví dụ Spring Boot remember me (Tự động login)

(Xem lại: Spring MVC Remember me)

(Xem lại: Ví dụ Spring Boot Security Hello + Tạo Form Login)

Bình thường sau khi đăng nhập, người dùng sẽ phải đăng nhập lại sau khi session timeout (thường là 30 phút hoặc cài đặt trong file web.xml) tuy nhiên với những trường hợp người dùng không muốn phải đăng nhập nhiều lần thì ta thường thấy có chức năng ‘remember me’, khi sử dụng chức năng này hệ thống sẽ ghi một cookie lên trình duyệt và người dùng sẽ không phải login lại sau khi session timeout.

Cấu hình Spring Boot Security Remember Me

Để bật chức năng Spring Security Remember Me ta cấu hình như sau:

http.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(1296000);

Trong đó method key() xác định key để mã hóa cookie được ghi ở browser (mặc định sẽ được generate ngẫu nhiên), method tokenValiditySeconds() sẽ xác định thời gian tồn tại cookies (thời gian tự động login có hiệu lực)

package stackjava.com.sbrememberme.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }
  
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).
      withUser("kai").password("$2a$04$Q2Cq0k57zf2Vs/n3JXwzmerql9RzElr.J7aQd3/Sq0fw/BdDFPAj.").roles("ADMIN");
//		auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("kai").password("123456").roles("USER");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    // Chỉ cho phép user đã đăng nhập mới được truy cập đường dẫn /admin/**
    http.authorizeRequests().antMatchers("/admin/**").authenticated();
    
    // Cấu hình remember me, thời gian là 1296000 giây
    http.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(1296000);

    // Cấu hình cho Login Form.
    http.authorizeRequests().and().formLogin()//
        .loginProcessingUrl("/j_spring_security_login")//
        .loginPage("/login")//
        .defaultSuccessUrl("/admin")//
        .failureUrl("/login?message=error")//
        .usernameParameter("username")//
        .passwordParameter("password")
        // Cấu hình cho Logout Page.
        .and().logout().logoutUrl("/j_spring_security_logout").logoutSuccessUrl("/login?message=logout");

  }
}

* Lưu ý, sau khi logout hoặc thay đổi password thì token remember me sẽ không còn tác dụng, ta phải login với remember me lại.

Trang login

Ở trang login ta sẽ thêm một ô checkbox với name là remember-me.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot Security Hello</title>
</head>
<body>
  <h2>Demo Spring Boot - Remember me</h2>
  <h3><p th:text="${message}"></p></h3>
  <form name='login-form' th:action="@{/j_spring_security_login}" method='POST'>
    <table>
      <tr>
        <td>Username:</td>
        <td><input type='text' name='username' value=''></td>
      </tr>
      <tr>
        <td>Password:</td>
        <td><input type='password' name='password' /></td>
      </tr>
      <tr>
                <td>Remember Me:</td>
                <td><input type="checkbox" name="remember-me" /></td>
            </tr>
      <tr>
        <td><input name="submit" type="submit" value="submit" /></td>
      </tr>
    </table>
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
  </form>
</body>
</html>

Demo

Login với tài khoản kai/123456 và chọn remember me:

Code ví dụ Spring Boot remember me (Tự động login)

Code ví dụ Spring Boot remember me (Tự động login)

Kiển thị cookie của trang web sau khi đăng nhập

Code ví dụ Spring Boot remember me (Tự động login)

Ta thấy có cookies ‘remember-me’ với thời gian hết hạn (username, password chứa trong nội dung)

Code ví dụ Spring Boot remember me (Tự động login)

Xóa cookie ‘JSESSIONID’ và tải lại trang /admin

Code ví dụ Spring Boot remember me (Tự động login)

Vẫn truy cập bình thường vì ta đã có cookie ‘remember-me’ chưa hết hạn.

Code ví dụ Spring Boot remember me (Tự động login)

Bây giờ bạn thử xóa cookie ‘JSESSIONID’ cho trường hợp login không chọn ‘Remember Me’ ta sẽ không thể truy cập được trang /admin mà buộc phải login lại.

Code ví dụ Spring Boot remember me (Tự động login) stackjava.com

Okay, Done!

Download code ví dụ trên tại đây.

 

 

References:

https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle

stackjava.com