栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第8章 Spring Security 会话

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第8章 Spring Security 会话

本章节就学习Spring Security会话的应用。例如,配置会话并发数、会话固定攻击与防御、Session共享等等。

会话并发管理

会话并发管理是指当前用户可以在系统存在多少会话,默认情况,会话是没有限制。当然我们配置一个用户只能有一个会话,这样就可以显示踢人下线。

配置

基于前面配置改造,这里主要罗列最主要的配置代码

@Configuration
public class UserWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/admin/**").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .defaultSuccessUrl("/hello1")
                .permitAll()
                .and()
                .csrf()
            .disable()
            .sessionManagement().maximumSessions(1).expiredUrl("/login");
       
    }
    
    // 增加session发布者:创建、销毁都发布事件
    @Bean
    HttpSessionEventPublisher sessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}

这里配置最大会话数为1,当会话过期时,会重定向到 /login 地址。我们可以通过 maxSessionsPreventsLogin() 配置禁止后来者登录。注意:这里我们需要重写自定义用户类 User 的 hashCode() 方法和 equals() 方法。

原理 SessionInfomation

SessionInformation 类是用来记录会话记录的。

public class SessionInformation implements Serializable {
    private static final long serialVersionUID = 510L;
    private Date lastRequest;
    private final Object principal;  // 表示用户
    private final String sessionId;  // 会话id
    private boolean expired = false;
    // getter and setter
}
SessionRegistry

SessioinRegistry 接口是用来保证会话的,当用户登录成功时,需要把会话保存起来。SessionRegistry 只有一个实现类 SessionRegistryImpl。它怎么来存储会话的呢?

public class SessionRegistryImpl implements SessionRegistry, 
ApplicationListener {
    
    // 一个用户可以有多个会话id
    private final ConcurrentMap> principals;
    // 会话id对应会话记录
    private final Map sessionIds;
    
    // 监听会话销毁时间
    public void onApplicationEvent(SessionDestroyedEvent event) {
        String sessionId = event.getId();
        this.removeSessionInformation(sessionId);
    }
}

SessionAuthenticationStrategy

SessionAuthenticationStrategy 接口用来定义如何去认证 session,例如 session 是否过期,会话数量是否超过规定等等。SessionAuthenticationStrategy 接口有7个实现类,这里是用到 策略设计模式 和 代理设计模式

踢人下线流程图

大概逻辑是:根据当前用户查询用户的会话记录表,判断会话记录表记录个数是否等于系统配置会话数。如果小于的话,说明此时会话并发说还没有达到,可以进行登录;否则,需要判断当前会话是否在会话记录表中存在,如果存在的话,说明是旧的会话;否则此时这个会话是新的会话,系统需要把会话记录表中最近最少使用的会话设置为过期。此时过滤器会来到 ConcurrentSessionFilter 过滤器。过滤器会调用 getSessionInformation() 根据当前会话Id查询会话记录,判断会话记录是否过期;如果没有过期,更新时间;否则,删除会话记录表一项,清空上下文,然后重定向到指定url

会话固定攻击与防御 什么是会话固定攻击

会话固定攻击:攻击者首先登录网站A,然后可以得到一个会话ID,然后攻击者构造一个带有会话ID的URL,让用户访问。当用户访问并登录后,攻击者就获取用户登录权限,可以以用户的身份访问。

会话固定攻击的防御策略

Spring Security提供一下几个策略:

  • Spring Security自带防火墙,可以拦截带有sessionId的请求。
  • Spring Security自带 ChangeSessionIdAuthenticationStrategy 策略,在用户登录后,改变会话ID。
  • 在Http响应设置 cookie 的 http-only 属性,防止XSS攻击读取cookie
配置

Spring Security 的配置方式如下所示:

http.sessionManagement().sessionFixation().changeSessionId();
  • changeSessionId():用户登录成功后,修改sessionId,默认就是此策略,实现类为 ChangeSessionIdAuthenticationStrategy
  • none() :用户登录成功后,不做任何变化,实现类为 NullAuthenticatedSessionStrategy
  • migrateSession():用户登录成功后,创建新的session,并把旧的Session的属性拷贝到新的Session中,实现类为 SessionFixationProtectionStrategy
  • newSession():用户登录成功,创建新的Session,并把旧的Session的以 SPRING_SECURITY_ 开头的属性拷贝到新的属性,实现类也是 SessionFixationProtectionStrategy ,这里将 migrateSessionAttributes 属性设置为 false
集群会话方案

在集群环境下,每个tomcat实例都会通过Spring Security维护自己的会话表,这样配置去管理会话并发的话,那必然会出现用户依赖可以在多个tomcat实例进行登录。

集群会话解决办法

一般解决集群会话有三个办法:

  • Session复制:多个服务器之间复制Session信息,这样每个服务器都有所有Session信息,Tomcat通过IP组播对这种办法提供支持。缺点是:占用宽带、有延时、服务数量越多越低效。

  • Session粘性:在Nginx上通过一致性hash,将相同的请求总是分发到服务器上。这样方案可以解决一部分集群Session问题,但是无法解决集群Session会话管理问题。

  • Session共享:通过Redis来存储集群所有Session。

参考

会话固定漏洞的一点学习、分析与思考

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/343702.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号