Lesson 3: Remember Me with Persistence

1. Main Goal

The focus of this lesson is to switch from the cookie based remember-me implementation to the persistence backed implemented that the framework provides.

2. Lesson Notes

The relevant module you need to import when you're starting with this lesson is: lssc-module3/m3-lesson3-start

If you want to skip and see the complete implementation, feel free to jump ahead and import: lssc-module3/m3-lesson3

A quick note is that this lesson is using MySQL, so you'll need to naturally have a MySQL Server running locally.

The credentials used in the code of this lesson are: [email protected]/pass (data.sql).

2.1. The Theory

The persistence backed implementation of remember-me is more secure than its cookie based counterpart with a mechanism that no longer relies on the username and passsword.

This means that the token generation mechanism doesn't use either the username or password to generate the cookie value.

And as a direct consequence, if a cookie gets compromised, it's enough to delete the persisted tokens and the user no longer needs to change their password to invalidate issued tokens. Also, the valid username is no longer exposed.

Next - the new remember me mechanism no longer validates the signature being present in the cookie - but the fact that the token is present in the DB.

2.2. The Implementation

Let's start by switching our persistence over to using MySQL just so that we can easily check the DB and see these tokens.

We're first going to define the MySQL dependency in Maven:


We are going to make use of Boot and the application.properties file to configure our persistence to use MySQL:


Now, over in our security configure, we are going to wire in the data source and start using it when defining a persistence repository for our tokens:

private DataSource dataSource;
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
    return jdbcTokenRepository;

Finally, we're going to make the switch from the cookie based implementation to the persistence backed one:


2.3. The DB Structure

Before we run everything, we need to make sure the DB structure necessary for storing our tokens is created as well:

create table if not exists persistent_logins (
  username varchar_ignorecase(100) not null,
  series varchar(64) primary key,
  token varchar(64) not null,
  last_used timestamp not null

We can make use of the data.sql file that Spring Boot uses by default for setting up data on startup here.

But, keep in mind that there are a lot of options to set up an initial DB structure when a project starts up - besides Spring Boot.

2.4. The Series

Finally, one quick note - I touched on the concept of the series in the video.

This series field identifies the login of the user and doesn't change for duration of the entire persistent session.

It also contains a random token, regenerated each time a user logs in via the persisted remember-me functions.

The goal is to make brute force attacks impossible in practice.

2.5. Upgrade Notes

Note that the video lesson is focused on Boot 1. Let's go over the relevant changes that have been present since version 2 of Boot.

First of all, some keys of the common application properties have changed:

  • server.tomcat.access_log_enabled has been renamed into server.tomcat.accesslog.enabled
  • server.sessionTimeout has been renamed into server.servlet.session.timeout

For newer Java and MySQL versions, note that we should use a different connector dependency:


And with this, we should now update the driver-class-name property as well:


Then, as we've already mentioned in previous lessons, since Spring Boot 2, it's required to specify the password encryption in order to configure the user detail service:

public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

It allows us as well to avoid storing the passwords in plain text format. It means that in our data.sql script that we use to populate the database once the application starts, we can now provide the encoded version of the password:

insert into user (id, email, password, ...) values (1, '[email protected]', NNN, ...);

where NNN is the encoded version of the user's password. It is important that we calculate the encoded version using the same encoder with which we configure the user detail service, i.e. the BCryptPasswordEncoder.

Since Spring Boot 2 the DataSource initialization feature is enabled by default only for embedded databases. Thus, if we want the application to execute the data.sql script on our MySQL database, we have to explicitly add the spring.sql.init.mode application property (or spring.datasource.initialization-mode for Boot versions prior to 2.5) assigning the "always" value to it.

Furthermore, we have to add the spring.jpa.defer-datasource-initialization=true property since we’re relying on the Hibernate to create the schema, but on the SQL script to populate it.

3. Resources

- Remember-Me - Persistent Token Approach (in the Official Reference)

- Persistent Remember-Me on Baeldung

LSS - Remember Me with Persistence - transcript.pdf
Complete and Continue