ch13:管理session,显示活跃用户数

Spring Security的一个常用配置就是检测相同的用户以不同的session登录系统。这称为concurrency control,是session管理一系列配置的一部分。Spring Security的session管理能够以两种不同的方式进行配置——session fixation protection(固化保护)和concurrency control(并发控制)。

配置session fixation保护

Session fixation protection是恶意用户试图窃取系统中一个未认证用户的session,在用户认证后,创建session副本,无需用户名和密码来访问用户信息的保护措施。攻击流程如图所示。


ch13:管理session,显示活跃用户数_第1张图片
Paste_Image.png

该类攻击的主要是利用了用户认证前后使用相同的session这个漏洞,其保护措施就是在用户认证后创建一个新的session,并令旧session失效。
Spring Security默认已经开启了Session Fixation Protection。下面的配置等同于默认开启设置

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //Spring Security的默认启用防止固化session攻击
                .and().sessionManagement().sessionFixation().migrateSession();
    }

sessionFixation可以设置三种方式:

  1. NONE,不启用Fixation保护
  2. migrateSession,启用Fixation保护,用户认证后创建新的session,并将旧session的属性复制到新session中。
  3. newSession,启用Fixation保护,用户认证后创建新的session,但是不复制旧session的属性。

配置session concurrency protection

设置了session fixation protection,自然会想到控制session的并发数量。session并发控制能够确保一个用户不能同时拥有超过一定数量的活跃session。配置Spring Security的session并发数非常简单:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/assets/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/**").hasRole("USER")
                .and().formLogin().loginPage("/login.jsp").permitAll().loginProcessingUrl("/login")
                .and().logout().permitAll()
                //自动识别tokenRepository类型,启用PersistentTokenBasedRememberMeServices
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                //Spring Security的默认启用防止固化session攻击
                .and().sessionManagement().sessionFixation().migrateSession()
                //设置session最大并发数为1,当建立新session时,原session将expired,并且跳转到登录界面
                .maximumSessions(1).expiredUrl("/login.jsp").sessionRegistry(sessionRegistry).and()
                .and().csrf().disable();
    }

这里设置session并发数为1,当用户在session失效前又创建另一session,则前一个session失效,并且再次访问时,自动跳转到/loging.jsp,要求用户再次认证。

获取系统在线用户总数

Spring Security会将认证的用户存储到Session Registry中,通过该类就可以获取当前在线用户数据,配置方法同上。Session Registry依赖HttpSessionEventPublisher,该类注册到服务容器中,就可以监听session状态的变化,而调整Session Registry。
配置HttpSessionEventPublisher:

/**
 * 以war包形式部署到web容器的启动类
 */
public class ApplicationServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(ApplicationInitializer.class);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        servletContext.addListener(new HttpSessionEventPublisher());
    }
}

为了获得当前用户信息,还需要配置一个Spring Registry Bean,默认Spring Security并未提供该类型的bean,我们需要明确声明,并将其配置给sessionManager()。

  @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

这样我们就可以将SessionRegistry注入到需要的地方,获取其提供的在线用户信息。

代码示例:https://github.com/wexgundam/spring.security/tree/master/ch13

你可能感兴趣的:(ch13:管理session,显示活跃用户数)