ch13:管理session,顯示活躍用戶數(shù)

Spring Security的一個(gè)常用配置就是檢測相同的用戶以不同的session登錄系統(tǒng)。這稱為concurrency control,是session管理一系列配置的一部分。Spring Security的session管理能夠以兩種不同的方式進(jìn)行配置——session fixation protection(固化保護(hù))和concurrency control(并發(fā)控制)。

配置session fixation保護(hù)

Session fixation protection是惡意用戶試圖竊取系統(tǒng)中一個(gè)未認(rèn)證用戶的session,在用戶認(rèn)證后,創(chuàng)建session副本,無需用戶名和密碼來訪問用戶信息的保護(hù)措施。攻擊流程如圖所示。


Paste_Image.png

該類攻擊的主要是利用了用戶認(rèn)證前后使用相同的session這個(gè)漏洞,其保護(hù)措施就是在用戶認(rèn)證后創(chuàng)建一個(gè)新的session,并令舊session失效。
Spring Security默認(rèn)已經(jīng)開啟了Session Fixation Protection。下面的配置等同于默認(rèn)開啟設(shè)置

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //Spring Security的默認(rèn)啟用防止固化session攻擊
                .and().sessionManagement().sessionFixation().migrateSession();
    }

sessionFixation可以設(shè)置三種方式:

  1. NONE,不啟用Fixation保護(hù)
  2. migrateSession,啟用Fixation保護(hù),用戶認(rèn)證后創(chuàng)建新的session,并將舊session的屬性復(fù)制到新session中。
  3. newSession,啟用Fixation保護(hù),用戶認(rèn)證后創(chuàng)建新的session,但是不復(fù)制舊session的屬性。

配置session concurrency protection

設(shè)置了session fixation protection,自然會(huì)想到控制session的并發(fā)數(shù)量。session并發(fā)控制能夠確保一個(gè)用戶不能同時(shí)擁有超過一定數(shù)量的活躍session。配置Spring Security的session并發(fā)數(shù)非常簡單:

    @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()
                //自動(dòng)識(shí)別tokenRepository類型,啟用PersistentTokenBasedRememberMeServices
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                //Spring Security的默認(rèn)啟用防止固化session攻擊
                .and().sessionManagement().sessionFixation().migrateSession()
                //設(shè)置session最大并發(fā)數(shù)為1,當(dāng)建立新session時(shí),原session將expired,并且跳轉(zhuǎn)到登錄界面
                .maximumSessions(1).expiredUrl("/login.jsp").sessionRegistry(sessionRegistry).and()
                .and().csrf().disable();
    }

這里設(shè)置session并發(fā)數(shù)為1,當(dāng)用戶在session失效前又創(chuàng)建另一session,則前一個(gè)session失效,并且再次訪問時(shí),自動(dòng)跳轉(zhuǎn)到/loging.jsp,要求用戶再次認(rèn)證。

獲取系統(tǒng)在線用戶總數(shù)

Spring Security會(huì)將認(rèn)證的用戶存儲(chǔ)到Session Registry中,通過該類就可以獲取當(dāng)前在線用戶數(shù)據(jù),配置方法同上。Session Registry依賴HttpSessionEventPublisher,該類注冊到服務(wù)容器中,就可以監(jiān)聽session狀態(tài)的變化,而調(diào)整Session Registry。
配置HttpSessionEventPublisher:

/**
 * 以war包形式部署到web容器的啟動(dòng)類
 */
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());
    }
}

為了獲得當(dāng)前用戶信息,還需要配置一個(gè)Spring Registry Bean,默認(rèn)Spring Security并未提供該類型的bean,我們需要明確聲明,并將其配置給sessionManager()。

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

這樣我們就可以將SessionRegistry注入到需要的地方,獲取其提供的在線用戶信息。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容