English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Spring Security 'Remember Me' feature

The 'Remember Me' feature allows users to access the application without re-login. The user's login session ends when the browser is closed, and if the user opens the browser again to access the application, it will prompt for login.

But we can use the 'Remember Me' feature to avoid re-login. It stores the user's identity in a Cookie or database and uses it to identify the user.

We are implementing this identity in the following example. Let's look at an instance.

Create a Maven project

First create a Maven project and provide project details.



Initially, the project looks like this:



Spring Security configuration

Configure the project to implement Spring security. It requires the following four Java files. First, create a package com.w3codebox and put all files into it.

//AppConfig.java

package com.w3codebox;
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.ComponentScan;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.servlet.config.annotation.EnableWebMvc;  
import org.springframework.web.servlet.view.InternalResourceViewResolver;  
import org.springframework.web.servlet.view.JstlView;  
@EnableWebMvc  
@Configuration  
@ComponentScan({ "com.w3codebox.controller.*" )  
public class AppConfig {  
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
        InternalResourceViewResolver viewResolver  
                          = new InternalResourceViewResolver();  
        viewResolver.setViewClass(JstlView.class);  
        viewResolver.setPrefix("/WEB-INF/views/");  
        viewResolver.setSuffix(".jsp");  
        return viewResolver;  
    }  
}

//MvcWebApplicationInitializer.java

package com.w3codebox;  
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  
public class MvcWebApplicationInitializer extends  
        AbstractAnnotationConfigDispatcherServletInitializer {  
    @Override  
    protected Class<?>[] getRootConfigClasses() {  
        return new Class[] { WebSecurityConfig.class };  
    }  
    @Override  
    protected Class<?>[] getServletConfigClasses() {  
        // TOdo Auto-generated method stub  
        return null;  
    }  
    @Override  
    protected String[] getServletMappings() {  
        return new String[] { "/};  
    }  
}

//SecurityWebApplicationInitializer.java

package com.w3codebox;  
import org.springframework.security.web.context.*;        
    public class SecurityWebApplicationInitializer  
        extends AbstractSecurityWebApplicationInitializer {  
    }

//WebSecurityConfig.java

In this class, we will also create users and perform authentication. The RememberMe() method within the configure() method is responsible for remembering and storing the user's identity.

package com.w3codebox;
import org.springframework.context.annotation.*;    
import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
import org.springframework.security.config.annotation.web.configuration.*;  
import org.springframework.security.core.userdetails.*;  
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;  
@EnableWebSecurity  
@ComponentScan("com.w3codebox)  
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
@Bean  
public UserDetailsService userDetailsService() {  
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();  
    manager.createUser(User.withDefaultPasswordEncoder()
    .username("admin").password("admin123).roles("ADMIN").build());  
    return manager;  
}  
  
@Override  
protected void configure(HttpSecurity http) throws Exception {  
    
      http.authorizeRequests().
      antMatchers("/index", "/user","/").permitAll()
      .antMatchers("/admin").authenticated()
      .and()
      .formLogin()
      .loginPage("/login)
      .and()
      .rememberMe()
      .key("rem-me-key)
      .rememberMeParameter("remember") // it is the name of checkbox at login page
      .rememberMeCookieName("rememberlogin") // it is the name of the cookie
      .tokenValiditySeconds(100) // remember for number of seconds
      .and()
      .logout()
      .logoutRequestMatcher(new AntPathRequestMatcher("/logout");  
}  
}

controller

In com.w3codebox.controller A controller named HomeController is created within the package. Please refer to the controller code.

//HomeController.java

package com.w3codebox.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HomeController {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index() {
        return "index";
    }
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        return "login";
    }
    @RequestMapping(value = "/admin", method = RequestMethod.GET)
    public String admin() {
        return "admin";
    }
}

View

Create a view (JSP page) to output the data to the browser.

//index.jsp

<html>  
<head>    
<title>Home Page</title>  
</head>  
<body>  
Welcome to w3codebox! <br> <br>
<a href="admin">Admin login</a>  
</body>  
</html>

//admin.jsp

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>Home Page</title>  
</head>  
<body>  
Welcome Admin! ??
<a href="logout">logout</a>  
</body>  
</html>

//login.jsp

This is our custom login page where we have added the "Remember me" checkbox. View the code.

<%@ taglib
    prefix="c"
    uri="http://java.sun.com/jsp/jstl/core" 
%>
<c:url value="/login" var="loginUrl"/>
<form action="${loginUrl}" method="post">       
    <c:if test="${param.error != null}">        
        <p>
            Invalid username and password.
        </p>
    </c:if>
    <c:if test="${param.logout != null}">       
        <p>
            You have been logged out.
        </p>
    </c:if>
    <p>
        <label for="username">Username</label>
        <input type="text" id="username" name="username"/>   
    </p>
    <p>
        <label for="password">Password</label>
        <input type="password" id="password" name="password"/>    
    </p>
    <p>
        <label for="remember"> Remember me</label>
        <input type="checkbox" name="remember" />
    </p>
    <input type="hidden"                        
        name="${_csrf.parameterName}"
        value="${_csrf.token}"/>
    <button type="submit" class="btn">Log in</button>
</form>

Project Dependencies

Below is our pom.xml file, which includes all necessary dependencies.

//pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.w3codebox/groupId>
  <artifactId>springrememberme/artifactId>
  <version>0.0.1-SNAPSHOT/version>
  <packaging>war</packaging>
  <properties>  
    <maven.compiler.target>1.8</maven.compiler.target>  
    <maven.compiler.source>1.8</maven.compiler.source>  
</properties>  
<dependencies>  
  <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-webmvc/artifactId>  
            <version>5.0.2.RELEASE</version>  
        </dependency>  
        <dependency>  
        <groupId>org.springframework.security</groupId>  
        <artifactId>spring-security-web/artifactId>  
        <version>5.0.0.RELEASE</version>  
    </dependency>  
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core/artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config/artifactId>
    <version>5.0.4.RELEASE</version>
</dependency>
    
      
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->  
<dependency>  
    <groupId>javax.servlet<//groupId>  
    <artifactId>javax.servlet-api</artifactId>  
    <version>3.1.0</version>  
    <scope>provided</scope>  
</dependency>  
<dependency>  
    <groupId>javax.servlet<//groupId>  
    <artifactId>jstl<//artifactId>  
    <version>1.2</version>  
</dependency>  
</dependencies>  
  <build>  
    <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins<//groupId>  
            <artifactId>maven-war-plugin</artifactId>  
            <version>2.6</version>  
            <configuration>  
                <failOnMissingWebXml>false<//failOnMissingWebXml>  
            </configuration>  
        </plugin>  
    </plugins>  
</build>  
</project>

Project Structure

After adding all files, the project structure will look like this:



Run the Server

Output:


 

Click the Admin login link and log in.



Look, we have Click 'Remember Me' Checkbox.



Copy URL: http://localhost:8080/springrememberme/admin And completely close the browser. After opening the second browser, paste the copied URL.

See, it will not require login and will log us into the same page. Because we indeed checked the 'Remember Me' button when we logged in.