问题是登录和所有事情都很有效,除了记住我的逻辑。未设置cookie,并且数据库中没有插入任何行。
这是安全配置类。
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=?");
}
}
这是令牌持久性的数据库表
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)
);
答案 0 :(得分:0)
Spring Security附带了PersistentTokenRepository的2个实现:JdbcTokenRepositoryImpl和InMemoryTokenRepositoryImpl。 我在我的应用程序中使用Hibernate,我使用Hibernate而不是使用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);
}
}
答案 1 :(得分:0)
我转载了同样的问题。使用调试功能,我检查了loginSuccess()方法的AbstractRememberMeServices类。
内部逻辑就像:
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
if (!this.rememberMeRequested(request, this.parameter)) {
this.logger.debug("Remember-me login not requested.");
} else {
this.onLoginSuccess(request, response, successfulAuthentication);
}
}
原来,我没有在用户登录时被标记为Remember Me
标记,所以我无法调用onLoginSuccess()方法,如果不能使用其他方法,则会陷入困境。 >
标记完标记后,我可以保留令牌和cookie。