1
1
.
.
8
8
.
.
3
3
L
L
o
o
g
g
i
i
n
n
F
F
o
o
r
r
m
m
-
-
D
D
e
e
f
f
a
a
u
u
l
l
t
t
-
-
D
D
B
B
-
-
P
P
o
o
s
s
t
t
g
g
r
r
e
e
S
S
Q
Q
L
L
I
I
n
n
f
f
o
o
This tutorial shows how to use Remember Me Cookie for Custom Login Form.
This requires you to manually add additional checkbox to your Custom Login Form (as shown below).
After successful Authentication through Custom Login Form, Remember Me Cookie will be stored in the User's Browser.
Remember Me Cookie will keep the User logged in permanently (even if Session Cookie has expired or was deleted).
That way next time User sends HTTP Request it will not have to Login again.
Application Schema [Results]
Spring Boot Starters
GROUP
DEPENDENCY
DESCRIPTION
Web
Spring Web
Enables @Controller, @RequestMapping and Tomcat Server.
Security
Spring Security
Enables Spring Security.
SQL
Spring Data JPA
Enables @Entity and @Id
SQL
PostgreSQL Database
Enables Hibernate to work with PostgreSQL DB
Developer Tools
Lombok
Enables @Data which generate helper methods (setters, getters, ...)
MyLogin.html
http://localhost:8080/MyLogin
Tomcat
MyController
http://localhost:8080/SayHello
sayHello()
myLogin()
SecurityConfig
P
P
r
r
o
o
c
c
e
e
d
d
u
u
r
r
e
e
Create Project: springboot_security_rememberme_db (add Spring Boot Starters from the table)
Edit File: application.properties (add Role, User, Password)
Create File: schema.sql (inside templates directory)
Create Package: config (inside main package)
– Create Class: SecurityConfig.java (inside package config)
– Create Class: SecurityBeans.java (inside package config)
Create Package: controllers (inside main package)
– Create Class: MyController.java (inside package controllers)
application.properties
# SECURITY
spring.security.user.name = myuser
spring.security.user.password = mypassword
spring.security.user.roles = USER
# POSTGRESQL DATABASE
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.url = jdbc:postgresql://localhost:5432/postgres
spring.datasource.username = postgres
spring.datasource.password = letmein
spring.datasource.initialization-mode = always
schema.sql
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);
SecurityBeans.java
package com.ivoronline.springboot_security_rememberme_db.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
@Configuration
public class SecurityBeans {
@Bean
public PersistentTokenRepository persistentTokenRepository(DataSource dataSource) {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}
}
SecurityConfig.java
package com.ivoronline.springboot_security_rememberme_db.config;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private final UserDetailsService userDetailsService;
private final PersistentTokenRepository persistentTokenRepository ;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//ENABLE REMEMBER ME COOKIE
httpSecurity.rememberMe()
.tokenRepository(persistentTokenRepository).userDetailsService(userDetailsService);
//H2 CONSOLE
httpSecurity.authorizeRequests(authorize -> { authorize.antMatchers("/h2-console/**").permitAll(); });
httpSecurity.headers().frameOptions().sameOrigin();
//DISABLE CSRF
httpSecurity.csrf().disable();
//SECURE EVERYTHING
httpSecurity.authorizeRequests().anyRequest().authenticated();
//DEfAULT LOGIN FORM
httpSecurity.formLogin();
}
}
MyController.java
package com.ivoronline.springboot_security_rememberme_db.controllers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@ResponseBody
@RequestMapping("/SayHello")
public String sayHello() {
return "Hello from Controller";
}
}
R
R
e
e
s
s
u
u
l
l
t
t
s
s
http://localhost:8080/SayHello
You get redirected to http://localhost:8080/MyLogin
– Username: myuser
– Password: mypassword
– Remember Me: CHECK
– Sign in
You get redirected back to http://localhost:8080/SayHello
Customize and control Google Chrome
– More Tools
– Developer Tools
– Application
– Cookies
– http://localhost:8080
http://localhost:8080/login http://localhost:8080/SayHello
remember-me Cookie
Persistent Token in DB Table: persistent_logins
Application Structure
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>