Spring Security usage memo Remember-Me

Basic and mechanical story Authentication / Authorization Story CSRF story Session management story The story of the response header Method security story CORS story The story of Run-As The story of ACL Test story Talk about cooperation with MVC and Boot

Extra edition What Spring Security can and cannot do

What is Remember-Me Authentication?

I often write "Keep logged in" or "Keep logged in for ○ weeks" on the login screen of Web services.

Hello World

Implementation

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">

    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:remember-me />★ Now Remember-Me is enabled
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="hoge"
                    password="hoge"
                    authorities="" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
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 java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().access("isAuthenticated()")
                .and()
                .formLogin()
                .and()
                .rememberMe(); //★ Remember here-Enable Me
    }
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("hoge")
            .password("hoge")
            .authorities(Collections.emptyList());
    }
}

Operation check

When you open the login screen (/ login), a checkbox called Remember me on this computer. is added (Default Login Screen. 032ed0fa27a239bdc1cc #% E3% 83% AD% E3% 82% B0% E3% 82% A4% E3% 83% B3% E3% 83% 9A% E3% 83% BC% E3% 82% B8% E3% 82% 92 Only if you are using% E6% 8C% 87% E5% AE% 9A% E3% 81% 99% E3% 82% 8B). At first, try logging in without checking it.

spring-security.jpg

After logging in, check your browser's cookies.

spring-security.jpg

The JSESSIONID is saved. Delete this and then redraw the screen.

spring-security.jpg

Naturally, you will be returned to the login screen.

Next, log in with the check box for Remember me on this computer. On the login screen checked.

spring-security.jpg

If you look at the cookie after logging in, you will see that JSESSIONID and another, remember-me, are stored.

spring-security.jpg

Delete JSESSIONID again and redraw the screen.

spring-security.jpg

Then, the screen can be redrawn without being skipped to the login screen. Looking at the cookie, JSESSIONID is stored with a different value than before.

How it works

--Remember-Me is enabled at login when a parameter named remember-me is added to the login parameters --The value can be empty because it seems that the parameter should be passed. --In short, just add <input type =" checkbox "name =" remember-me "/> to your login page. --If you log in with Remember-Me enabled, a cookie called remember-me will be added. --This cookie is Base64-encoded by concatenating "user name", "expiration date", and "signature" with a colon (:). ――The "signature" is made by concatenating the "user name", "expiration date", "password", and "KEY (details will be described later)" and hashing them with MD5.

spring-security.jpg

--If you access without logging in, the "expiration date" and "signature" will be extracted from this cookie, and the following verification will be performed. --Is the "expiration date" expired? --Recreate the "signature" from the cookie information and user information stored on the server side, and is it equal to the value stored in the cookie? --If there is no problem in the verification, you will be automatically logged in. --If the "expiration date" has expired or the comparison result of "signature" is different, an authentication error will occur.

About KEY

The KEY used for signing points to any string that can be specified in the key attribute of<remember-me>in the configuration file.

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        ...
        <sec:remember-me key="foobar" />
    </sec:http>
    
    ...
</beans>

However, this attribute is optional, otherwise a random string generated using SecureRandom will be used.

I think it's safer to use SecureRandom, but this value is only generated once when the application starts. So, if you restart the application while using SecureRandom, all the remember-me cookies recorded by the client will be invalidated. (When the KEY changes, the signature value also changes, so an error always occurs when verifying the signature.)

If you want to keep the remember-me cookie that the client has even if you restart the application, it seems that you need to specify a fixed string.

Precautions when using the default Remember-Me

――Because of the above mechanism, if you know the cookie value, you can easily spoof. --Also, if accessed by a stolen cookie, the system cannot identify whether it is a stolen cookie. ――It should be noted that the default Remember-Me mechanism weakens security.

What you should do if you use it in earnest

Enable the secure attribute of cookies

If you enable the secure attribute of the cookie, the cookie will be sent only for https communication. If you send a cookie over unencrypted http communication, it may be intercepted by a third party and the cookie may be stolen, so this setting should be enabled.

If you are using Spring Securty, you can enable the secure attribute of the cookie used by Remember-Me by setting as follows.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        ...
        <sec:remember-me use-secure-cookie="true" />
    </sec:http>
    
    ...
</beans>

Set true to the ʻuse-secure-cookie attribute of the `tag.

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
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 java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .useSecureCookie(true);
    }
    
    ...
}

ʻUseSecureCookie (true)` is set.

Do not allow important processing to be performed when logging in with Remember-Me

Do not completely trust Remember-Me logins and require password authentication again before any really important process. Important processing includes, for example, updating data or accessing a page displaying personal information.

By doing so, even if the Remember-Me cookie is stolen and spoofed, you can protect it from performing really important actions.

I think that's the one who often asks for a password before confirming an order on an online shopping site (probably).

For Spring Security, Access Control Expressions (http://qiita.com/opengl-8080/items/032ed0fa27a239bdc1cc#%E5%BC%8F%E3%83%99%E3%83%BC%E3% 82% B9% E3% 81% A7% E3% 81% AE% E3% 82% A2% E3% 82% AF% E3% 82% BB% E3% 82% B9% E5% 88% B6% E5% BE% In A1), you can use an expression that considers that it is not Remember-Me, such as ʻisFullyAuthenticated ()`, so it can be realized by using it.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/remember-me/high-level" access="isFullyAuthenticated()" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        ...
        <sec:remember-me />
    </sec:http>
    
    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
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 java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/remember-me/high-level").fullyAuthenticated()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe();
    }
    
    ...
}

It is set so that if you access / remember-me / high-level, you must be fully authenticated (fullyAuthenticated () ).

In addition, we have prepared a simple Servlet that just returns the path at that time when accessing / remember-me / *.

** Operation check **

spring-security.jpg

Log in with Remember-Me enabled.

spring-security.jpg

Remove JSESSIONID from the cookie (make it the same as dead session).

If you access the top page again in this state, automatic login by Remember-Me will be executed and the top page will be displayed.

Access / remember-me / foo after logging in with Remember-Me.

spring-security.jpg

The page is displayed normally. Then go to / remember-me / high-level.

spring-security.jpg

This time you will be taken to the login page. This is because / remember-me / high-level is set to fullyAuthenticated, that is, only a complete login with a password can be viewed.

Enter your password to log in.

spring-security.jpg

This time, / remember-me / high-level is displayed properly.

Spring Security automatically controls the transition destination after login to the URL you were trying to access before login, so no special settings are required (any URL can be specified).

Detect that cookies have been stolen

With the default Remember-Me mechanism described above, it is not possible to determine if a cookie has been stolen by a third party. Therefore, the victim does not notice that he / she has been damaged and gives the attacker a margin to do whatever he / she wants.

Therefore, Spring Security provides a mechanism that can detect whether a cookie has been stolen in order to minimize the damage.

Mechanism to detect stolen

Spring Security implements a theft detection mechanism by adopting the mechanism described in the article here.

Roughly speaking, the handling of cookies is as follows.

spring-security.jpg

The contents of the cookie are "series" and "token". And the server records the combination of the two.

At the time of automatic login, the "token" recorded by the server is searched for in the "series" extracted from the cookie, and it is verified whether it matches the "token" in the cookie.

Automatic login is performed only if the "token" matches, after which the "token" is replaced with the new value.

This mechanism of using the "series" that reuses values as an identifier to identify the cookie and updating the "token" each time an automatic login is performed is a mechanism for detecting theft.

If the attacker automatically logs in with the stolen cookie, the "token" contained in the attacker's cookie and the "token" recorded by the server are updated, but the victim's cookie "token" is updated. Will remain old.

Therefore, if the victim attempts to log in automatically after an unauthorized login, the "token" recorded on the server side and the "token" held by the victim's cookie will not match.

spring-security.jpg

This will allow the server to detect that the cookie may have been stolen and notify the victim or service administrator.

This is my personal opinion, but I feel that the shorter the session timeout, the sooner the theft can be detected. However, in that case, session timeouts will occur frequently, and you will have to enter the password every time you try to open a screen that requires a complete login as described above, which seems to reduce usability. (Depending on whether you prioritize security or ease of use).

Random character strings generated using SecureRandom are used for" series "and" token ".

Enable theft detection mechanism in Spring Security

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    compile 'org.springframework:spring-jdbc:4.3.7.RELEASE' ★
}

Added spring-jdbc to dependencies.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <bean id="rememberMeTokenRepository"
          class="org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl" />
    
    <sec:http>
        ...
        <sec:remember-me token-repository-ref="rememberMeTokenRepository" />
    </sec:http>
    
    ...
</beans>

ʻInMemoryTokenRepositoryImpl is added to the bean definition and specified in token-repository-refof the` tag.

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
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.web.authentication.rememberme.InMemoryTokenRepositoryImpl;

import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/remember-me/high-level").fullyAuthenticated()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .tokenRepository(new InMemoryTokenRepositoryImpl()); ★
    }
    
    ...
}

Pass an instance of ʻInMemoryTokenRepositoryImpl with tokenRepository () `.

spring-security.jpg

Log in with Remember-Me enabled.

spring-security.jpg

Copy the value of the issued cookie.

spring-security.jpg

Open another browser and add remember-me to the cookie to set the value you just copied.

spring-security.jpg

If you access the top page, you can log in without entering a password (the attack was successful).

In this state, return to the browser that was originally password-logged in, delete JSESSIONID, and then access the top page. (Reproduction of the state where the victim accessed again after the session expired)

spring-security.jpg

CookieTheftException is thrown and an error screen appears.

By default, even if an exception that means cookie theft is thrown, it does not seem to be handled and it is treated as a system error. (For the time being, we have detected that the cookie has been stolen.)

Classes that appear

spring-security.png

The Remember-Me process is started by RememberMeAuthenticationFilter. If there is access in the unauthenticated state, this Filter delegates the authentication process to RememberMeService.

RememberMeService has two implementation classes. TokenBasedRememberMeServices implements Remember-Me authentication by the simple method we saw in the first Hello World. On the other hand, PersistentTokenBasedRememberMeServices realizes Remember-Me by a method that can detect theft, which will be described later.

PersistentTokenBasedRememberMeServices delegates the storage of" series "and" tokens "to PersistentTokenRepository, and PersistentTokenRepository has two classes depending on the specific storage method. JdbcTokenRepositoryImpl records information in a database table, and ʻInMemoryTokenRepositoryImpl` records it in memory.

If you just enable Remember-Me, TokenBasedRememberMeServices is used to implement RememberMeService. However, you can switch the implementation of RememberMeService to PersistentTokenBasedRememberMeServices by specifying PersistentTokenRepository in token-repository-ref.

Error handling when cookie theft is detected

A CookieTheftException is thrown when a cookie theft is detected. However, when trying to handle this exception, it seems that the API provided by Spring Security cannot achieve it.

The CookieTheftException thrown by PersistentTokenBasedRememberMeServices is once caught by ʻAbstractRememberMeServices`. Then, after the cookie is cleared, it is thrown again.

After that, it will not be caught anywhere and will fly to the Servlet.

Therefore, if you try to handle this exception, you have no choice but to use the Servlet standard exception handling mechanism.

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    
    ...
    
    <error-page>
        <exception-type>org.springframework.security.web.authentication.rememberme.CookieTheftException</exception-type>
        <location>/cookie-theft.html</location>
    </error-page>
</web-app>

cookie-theft.html


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>CookieTheftException</title>
    </head>
    <body>
        <h1>The cookie was stolen!</h1>
    </body>
</html>

If you operate so that CookieTheftException is thrown, the stack trace error screen will not be displayed and you will be skipped to the next screen.

spring-security.jpg

Since Servlet can define the transition destination when an error occurs in web.xml with the<error-page>tag, use this. In the case of the above example, only static pages can be displayed, but dynamic processing can be inserted by combining with Servlet.

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    
    ...
    
    <error-page>
        <exception-type>org.springframework.security.web.authentication.rememberme.CookieTheftException</exception-type>
        <location>/cookie-theft</location>
    </error-page>
</web-app>

CookieTheftServlet.java


package sample.spring.security.servlet;

import org.springframework.security.web.authentication.rememberme.CookieTheftException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/cookie-theft")
public class CookieTheftServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CookieTheftException e = (CookieTheftException)req.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        try (PrintWriter writer = resp.getWriter()) {
            writer.println(e.getMessage());
        }
    }
}

State when an error occurs spring-security.jpg

Make sure that the Servlet accepts the path specified by <location> of <error-page>. In this Servlet, you can refer to error information such as exception objects by using getAttribute () from HttpServletRequest.

I haven't tried it, but if you're using Spring MVC, I think you can make it accepted by the MVC Controller.

In any case, this allows you to perform arbitrary processing, so you can send error information by e-mail.

Save to database

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    compile 'org.springframework:spring-jdbc:4.3.7.RELEASE'
    compile 'com.h2database:h2:1.4.193'
}

For the database, use H2 of the embedded database for the time being.

src/main/resources/sql/create_remember-me_tables.sql


CREATE TABLE PERSISTENT_LOGINS (
    USERNAME  VARCHAR(64) NOT NULL,
    SERIES    VARCHAR(64) NOT NULL PRIMARY KEY,
    TOKEN     VARCHAR(64) NOT NULL,
    LAST_USED TIMESTAMP   NOT NULL
);

An SQL file that creates a table for recording token information.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       ...
       xsi:schemaLocation="
         ...
         http://www.springframework.org/schema/jdbc
         http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
    
    ...
    
    <jdbc:embedded-database id="dataSource" type="H2">
        <jdbc:script location="classpath:/sql/create_remember-me_tables.sql" />
    </jdbc:embedded-database>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/remember-me/high-level" access="isFullyAuthenticated()" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:remember-me data-source-ref="dataSource" />
    </sec:http>
    
    ...
</beans>

Define the data source as a bean and specify it in the data-source-ref attribute of the<remember-me>tag.

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
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.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;
import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .tokenRepository(this.createTokenRepository());
    }
    
    public PersistentTokenRepository createTokenRepository() {
        DataSource dataSource =
                new EmbeddedDatabaseBuilder()
                    .generateUniqueName(true)
                    .setType(EmbeddedDatabaseType.H2)
                    .setScriptEncoding("UTF-8")
                    .addScript("/sql/create_remember-me_tables.sql")
                    .build();

        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        
        return tokenRepository;
    }
    
    ...
}

Java Configuration doesn't seem to have a method to specify DataSource directly, so set DataSource to JdbcTokenRepositoryImpl and then pass it withtokenRepository ()method.

Customize the table that stores tokens

As I saw the implementation, it seems impossible to customize the table name and column name only with the standard implementation. The implementation of JdbcTokenRepositoryImpl looks like this:

JdbcTokenRepositoryImpl.java


public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements
		PersistentTokenRepository {
	// ~ Static fields/initializers
	// =====================================================================================

	/** Default SQL for creating the database table to store the tokens */
	public static final String CREATE_TABLE_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)";
	/** The default SQL used by the <tt>getTokenBySeries</tt> query */
	public static final String DEF_TOKEN_BY_SERIES_SQL = "select username,series,token,last_used from persistent_logins where series = ?";
	/** The default SQL used by <tt>createNewToken</tt> */
	public static final String DEF_INSERT_TOKEN_SQL = "insert into persistent_logins (username, series, token, last_used) values(?,?,?,?)";
	/** The default SQL used by <tt>updateToken</tt> */
	public static final String DEF_UPDATE_TOKEN_SQL = "update persistent_logins set token = ?, last_used = ? where series = ?";
	/** The default SQL used by <tt>removeUserTokens</tt> */
	public static final String DEF_REMOVE_USER_TOKENS_SQL = "delete from persistent_logins where username = ?";

	// ~ Instance fields
	// ================================================================================================

	private String tokensBySeriesSql = DEF_TOKEN_BY_SERIES_SQL;
	private String insertTokenSql = DEF_INSERT_TOKEN_SQL;
	private String updateTokenSql = DEF_UPDATE_TOKEN_SQL;
	private String removeUserTokensSql = DEF_REMOVE_USER_TOKENS_SQL;

        ...

SQL text is defined in the public`` static field and is set in the field when the instance is created. The SQL set in this field is used when searching for tokens, but there is no method to rewrite this field. So it seems that it can't be rewritten (seriously? Is it something wrong?).

If you cannot specify the table name or column name due to adult circumstances, you may need to copy JdbcTokenRepositoryImpl to create your ownTokenRepository.

reference

Recommended Posts

Spring Security usage memo Remember-Me
Spring Security usage memo CSRF
Spring Security usage memo Run-As
Spring Security Usage memo Method security
Spring Security usage memo CORS
Spring Security usage memo test
Spring Security usage memo Authentication / authorization
Spring Security usage memo response header
Spring Security usage memo session management
Spring Security usage memo Basic / mechanism
Spring Security Usage Memo Domain Object Security (ACL)
Spring Shell usage memo
JavaParser usage memo
WatchService usage memo
PlantUML usage memo
JUnit5 usage memo
JJUG CCC Spring 2018 memo
About Spring Security authentication
Spring boot memo writing (1)
Spring Security causes 403 forbidden
Spring boot memo writing (2)
[Personal memo] About Spring framework
JJUG CCC 2018 Spring participation memo
Spring Framework self-study memo series_1
Login function with Spring Security
[Spring Security] Spring Security on GAE (SE)
Dependency Management Plugin Usage memo
Try using Spring Boot Security
Spring boot controller method memo
Implemented authentication function with Spring Security ②
◆ Spring Boot + gradle environment construction memo
JCA (Java Cryptography Architecture) Usage Memo
Implemented authentication function with Spring Security ③
Spring Boot Tutorial Using Spring Security Authentication
spring framework Simple study memo (2): AOP
Implemented authentication function with Spring Security ①
Learn Spring Security authentication processing architecture
Memo after the first Spring project-MVC-
A memo that touched Spring Boot
Spring thorough introduction version upgrade memo
Authentication / authorization with Spring Security & Thymeleaf
Memo after the first Spring project-Database-
Thymeleaf usage notes in Spring Boot
Spring5 MVC Web application development with Visual Studio Code Spring Security usage 1/3 [Preparation]