创建数据库表
CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
也可以不手动创建,JdbcTokenRepositoryImpl中有定义的sql,能自动创建
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 = ?";
WebSecurityConfig注入数据源、配置操作数据库对象
/**
* 注入数据源
*/
@Autowired
private DataSource dataSource;
/**
* 配置对象
* @return
*/
@Autowired
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//启动的时候将表创建
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
配置自动登录
@Override
protected void configure(HttpSecurity http) throws Exception {
//访问/logout退出后,跳转到到test/hello路径
http.logout().logoutUrl("/logout")
.logoutSuccessUrl("/test/hello").permitAll();
http
//自定义自己编写的登录页面
.formLogin()
//登录页面设置
.loginPage("/login.html")
//登录访问路径
.loginProcessingUrl("/user/login")
//登录成功之后,跳转路径
.defaultSuccessUrl("/success.html").permitAll()
//设置那些路径可以直接访问,不需要认证
.and().authorizeRequests()
.antMatchers("/","/test/hello","/test/erro").permitAll()
//当前登录用户,只有具备admins权限才可以访问这个路径
//.antMatchers("/test/index").hasAuthority("admins")
//当前登录用户,只要具备其中一个权限就可以访问这个路径
//.antMatchers("/test/index").hasAnyAuthority("admins","manager")
//当前登录用户,只有具备sale角色才可以访问这个路径
//.antMatchers("/test/index").hasRole("sale")
//当前登录用户,只要具备其中一个角色就可以访问这个路径
.antMatchers("/test/index").hasAnyRole("sale","role")
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
//设置自动登录
.and().rememberMe().tokenRepository(persistentTokenRepository())
//设置自动登录有效时长,单位秒
.tokenValiditySeconds(20)
//设置自动登录操作数据库
.userDetailsService(userDetailsService)
// CSRF禁用,因为不使用session
.and().csrf().disable();
}
登录界面增加记住我选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/api/auth/user/login" method="post">
<input type="text" name="username" placeholder="输入用户名"/>
<input type="text" name="password" placeholder="输入密码"/>
<input type="checkbox" name="remember-me"/>自动登录
<br>
<button>登录</button>
</form>
</body>
</html>
此处:name 属性值必须位 remember-me.不能改为其他值
访问控制
@GetMapping("update")
//@Secured({"ROLE_role","ROLE_manager"})
//@PreAuthorize("hasAnyAuthority('admins')")
@PostAuthorize("hasAnyAuthority('admins')")
public String update(){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = dateFormat.format(new Date());
//获取当前时间后的30秒
Date date = new Date(System.currentTimeMillis()+30*1000);
String e = dateFormat.format(date);
return "自动登录开始时间->"+s+" 过期时间->"+e;
}
测试
1、查看Cookie变化
2、数据库变化
3、有效时长准确性,维护的时间和北京时间相差8个小时,是时区影响导致,我们只看分秒
4、在有效期内关掉游览器是否能自动登录,过期后是否需要再次登录
动态图片太大了,上传不上来可以跳到有道笔记上去看:图片
以上都已实现;