Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security token persistence storage not working

The problem is that the login and all things are working great except the remember me logic. The cookie is not set and there is no rows are inserted in the database.

This is the security configuration class.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

/**
 * Spring security configurations.
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // Authorize all requests
                .authorizeRequests()
                    // Allow only admins to access the administration pages
                    .antMatchers("/admin/**").access("hasRole('ADMIN')")
                    // Allow any one to access the register and the main pages only alongside
                    // the resources files that contains css and javascript files
                    .antMatchers("/resources/**", "/register", "/").permitAll()
                    // Authenticate any other request
                    .anyRequest().authenticated()
                    .and()
                // Set up the login form.
                .formLogin()
                    //.successHandler(successHandler())
                    .loginPage("/login")
                    .usernameParameter("email").passwordParameter("password")
                    .permitAll()
                    .and()
                // Enable remember me cookie and persistence storage
                .rememberMe()
                    // Database token repository
                    .tokenRepository(persistentTokenRepository())
                    // Valid for 20 days
                    .tokenValiditySeconds(20 * 24 * 60 * 60)
                    .rememberMeParameter("remember-me")
                    .and()
                // Log out handler
                .logout()
                    .permitAll()
                    .and()
                // Enable Cross-Site Request Forgery
                .csrf();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
        db.setDataSource(dataSource);
        return db;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // Provide database authentication and swl queries to fetch the user's data..
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select email, password, enabled from users where email=?")
                .authoritiesByUsernameQuery("select us.email, ur.role from users us, " +
                        " roles ur where us.role_id=ur.id and us.email=?");
    }
}

and this is the database table for token persistence

CREATE TABLE persistent_logins (
    username VARCHAR(254) NOT NULL,
    series VARCHAR(64) NOT NULL,
    token VARCHAR(64) NOT NULL,
    last_used TIMESTAMP NOT NULL,
    PRIMARY KEY (series)
);
like image 929
Ahmed Hegazy Avatar asked Jul 04 '26 09:07

Ahmed Hegazy


1 Answers

Spring Security comes with 2 implementation of PersistentTokenRepository : JdbcTokenRepositoryImpl and InMemoryTokenRepositoryImpl. I'm using Hibernate in my application, i create a custom implementation using Hibernate instead of using JDBC.

@Repository("tokenRepositoryDao")
@Transactional
public class HibernateTokenRepositoryImpl extends AbstractDao<String, PersistentLogin>
        implements PersistentTokenRepository {

    static final Logger logger = LoggerFactory.getLogger(HibernateTokenRepositoryImpl.class);

    @Override
    public void createNewToken(PersistentRememberMeToken token) {
        logger.info("Creating Token for user : {}", token.getUsername());
        PersistentLogin persistentLogin = new PersistentLogin();
        persistentLogin.setUsername(token.getUsername());
        persistentLogin.setSeries(token.getSeries());
        persistentLogin.setToken(token.getTokenValue());
        persistentLogin.setLast_used(token.getDate());
        persist(persistentLogin);

    }

    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId) {
        logger.info("Fetch Token if any for seriesId : {}", seriesId);
        try {
            Criteria crit = createEntityCriteria();
            crit.add(Restrictions.eq("series", seriesId));
            PersistentLogin persistentLogin = (PersistentLogin) crit.uniqueResult();

            return new PersistentRememberMeToken(persistentLogin.getUsername(), persistentLogin.getSeries(),
                    persistentLogin.getToken(), persistentLogin.getLast_used());
        } catch (Exception e) {
            logger.info("Token not found...");
            return null;
        }
    }

    @Override
    public void removeUserTokens(String username) {
        logger.info("Removing Token if any for user : {}", username);
        Criteria crit = createEntityCriteria();
        crit.add(Restrictions.eq("username", username));
        PersistentLogin persistentLogin = (PersistentLogin) crit.uniqueResult();
        if (persistentLogin != null) {
            logger.info("rememberMe was selected");
            delete(persistentLogin);
        }

    }

    @Override
    public void updateToken(String seriesId, String tokenValue, Date lastUsed) {
        logger.info("Updating Token for seriesId : {}", seriesId);
        PersistentLogin persistentLogin = getByKey(seriesId);
        persistentLogin.setToken(tokenValue);
        persistentLogin.setLast_used(lastUsed);
        update(persistentLogin);
    }

}
like image 86
FuSsA Avatar answered Jul 07 '26 04:07

FuSsA



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!