Spring Security记住我令牌仅生效一次问题求助
Hey there, let's figure out why your remember-me functionality is only working for one automatic login—this is a super common issue with a handful of straightforward fixes. Let's break down the most likely causes and how to resolve them:
1. You're Using the In-Memory Token Repository (Default Behavior)
By default, Spring Security uses InMemoryTokenRepositoryImpl for remember-me tokens if you don't specify a persistent storage option. The problem with this implementation is that it invalidates the old token every time a successful authentication (including remember-me logins) happens.
Here's exactly what's playing out in your flow:
- You log in normally, a remember-me token gets stored in memory.
- You delete
JSESSIONIDand refresh: Spring uses the remember-me token to authenticate you, generates a new token, and discards the old one. But your browser still holds the original remember-me cookie. - You delete
JSESSIONIDagain and refresh: Now Spring tries to validate the original token from your cookie, but it's already been removed from memory—so authentication fails.
Fix: Switch to a Database-Backed Token Repository
Use JdbcTokenRepositoryImpl to store tokens in your database, which properly updates tokens instead of discarding them entirely. Here's how to set it up:
First, create the required table in your database (you can let Spring auto-create it on first startup, then comment out that line later):
CREATE TABLE persistent_logins ( username VARCHAR(64) NOT NULL, series VARCHAR(64) PRIMARY KEY, token VARCHAR(64) NOT NULL, last_used TIMESTAMP NOT NULL );
Then update your Spring Security configuration:
@Bean public PersistentTokenRepository persistentTokenRepository(DataSource dataSource) { JdbcTokenRepositoryImpl tokenRepo = new JdbcTokenRepositoryImpl(); tokenRepo.setDataSource(dataSource); // Uncomment once to create the table, then comment it out // tokenRepo.setCreateTableOnStartup(true); return tokenRepo; } @Override protected void configure(HttpSecurity http) throws Exception { http // ... your other security configs ... .rememberMe() .tokenRepository(persistentTokenRepository(dataSource)) .tokenValiditySeconds(86400) // Set token validity (e.g., 1 day) .userDetailsService(yourUserDetailsService); // Ensure this is wired correctly }
2. Check Your User Entity's equals() and hashCode() Methods
Spring Security relies on correctly implemented equals() and hashCode() for your User object to look up users during remember-me authentication. If these methods are defined incorrectly (e.g., using a mutable field like a session ID, or missing unique attributes like username), Spring might fail to find the user on the second authentication attempt.
Make sure these methods are based on immutable, unique attributes of your user (like username or user ID).
3. Verify No Custom Logic Is Deleting Tokens
If you have custom authentication success handlers, event listeners, or post-login cleanup logic, double-check that it isn't accidentally removing remember-me tokens from the repository. Some developers add logic to clear old tokens on login, but overly aggressive cleanup can invalidate the current token prematurely.
4. Check the Full Error Message
Your console error was cut off, but if you see something like:
Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack?
This confirms the token mismatch issue caused by the in-memory repository—switching to the JDBC repository will fix this immediately.
内容的提问来源于stack exchange,提问作者guidev

