学习基于记录,而不止于记录。
希望自己能坚持下去~
0.写在前面
继续上一篇,本篇用于通过对session进行管理和配置,实现控制登录设备上限,以及超出限制后,提示被踢下线的使用场景。
spring boot版本:2.2.7.RELEASE
开发工具:IntelliJ IDEA 2018.3.2 (Ultimate Edition)
jdk: java version "1.8.0_181"
maven: 3.3.9
1.session 限制
//最大登陆人数为1
.maximumSessions(1)
//设置false允许多点登录但是,如果超出最大人数之前的登录会被踢掉
.maxSessionsPreventsLogin(false)
.expiredSessionStrategy(myExpiredSessionStrategy); //在此自定义踢下线配置
2.完整配置文件
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
MyAuthenticationFailureHandler myAuthenticationFailureHandler;
@Autowired
MyExpiredSessionStrategy myExpiredSessionStrategy;
@Override
protected void configure(HttpSecurity http) throws Exception {
//关闭这项拦截功能,要不然后面测试都无法进行
http.csrf().disable();
//登录任何人都可以访问
//pageA和pageB只有拥有user或者admin权限才可以访问
//syslog和sysuser只有拥有admin权限才可以访问
http.formLogin()
.loginPage("/login.html")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")
.failureHandler(myAuthenticationFailureHandler)
.successHandler(myAuthenticationSuccessHandler)
.and()
.authorizeRequests()
.antMatchers("/login.html", "/login", "/expired", "/jwt-expired.html").permitAll()
.antMatchers("/pageA.html", "pageB.html")
.hasAnyAuthority("ROLE_user", "ROLE_admin")
.antMatchers("/syslog.html", "/sysuser.html")
.hasAnyAuthority("ROLE_admin")
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
// .invalidSessionUrl("/login.html") // 设置 Session 会话失效时重定向路径,默认为 loginPage()
.sessionFixation()
.migrateSession()
//最大登陆人数为1
.maximumSessions(1)
//设置false允许多点登录但是,如果超出最大人数之前的登录会被踢掉
.maxSessionsPreventsLogin(false)
.expiredSessionStrategy(myExpiredSessionStrategy);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles("user")
.and()
.withUser("admin")
.password(passwordEncoder().encode("123456"))
// .authorities("/syslog", "/sysuser")
.roles("admin")
.and()
.passwordEncoder(passwordEncoder()); //配置加密方式
}
//加密方式
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
3.自定义配置seesion过期策略
3.1 挤下线后,跳转提示页面
@Component
public class MyExpiredSessionStrategy implements SessionInformationExpiredStrategy {
//页面跳转
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
redirectStrategy.sendRedirect(event.getRequest(), event.getResponse(),"/expired"); //提示页面路由
}
}
3.2 前后端分离的架构,提供json返回
@Component
public class MyExpiredSessionStrategy implements SessionInformationExpiredStrategy {
private static ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
System.out.println("凭证过期了,,,,,,");
event.getResponse().setContentType("application/json;charset=UTF-8");
event.getResponse().getWriter().write(objectMapper.writeValueAsString(MyResponse.getSessionExpiredInstance()));
}
}
演示我就不截图了,可以在两个浏览器模拟两端登录,最终只有一个可以保持在登陆状态,剩下全部会丢失凭证信息。
4.总结
这部分本质还是session会话管理的延续,主要通过配置控制同账号最多登陆限制,外加上自定义session过期处理策略实现页面的页面提示。