单体项目中的session会话共享
对于我们的web项目,我们可以在ss的配置里面配置下面的内容。
包含了传统web项目的跳转路径以及前后端分离项目用户会话被挤下线之后的处理策略。
同时我们还可以指定用户在其他设备上登录了之后无法再次登录,避免用户被挤下线的情况发生。
.csrf().disable()
.sessionManagement()
.maximumSessions(2)
// .expiredUrl("")//传统项目的用户被挤下线之后的跳转路径
//下面这个是前后端分离web项目的用户被挤下线之后的返回操作
.expiredSessionStrategy(event -> {
HttpServletResponse response = event.getResponse();
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("并发登录");
response.flushBuffer();
})
.maxSessionsPreventsLogin(true)//登录了之后禁止登录,这样,一旦登录就会禁止其他用户登录,不会发送被挤下线的情况了
底层实现
ss中相关的类是SessionManagementFilter
和SessionAuthenticationStrategy
,SessionManagementFilter
将相关的操作委托给后者来处理。
底层的实现原理,简单地来说实际上就是维护了一个map,记录用户以及对应的session。如果允许再次登录就会在用户在新的设备登录的时候更新对应的session,原来用户的session就会失效。不允许再次登录就是在用户再次登录的时候发现map里面已经存在了用户的session了就会直接返回错误信息。这种方式对于传统的单体的项目来说是比较容易实现的,但是在微服务项目里面我们如何实现呢?
分布式项目中的session共享
我们可以把session存储到redis当中
首先引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
在构造方法中注入FindByIndexNameSessionRepository
,这个是用来将session序列化到redis的工具
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final MyUserDetailService myUserDetailService;
private final DataSource dataSource;
private final FindByIndexNameSessionRepository findByIndexNameSessionRepository;
@Autowired
public WebSecurityConfiguration(MyUserDetailService myUserDetailService,DataSource dataSource
,FindByIndexNameSessionRepository findByIndexNameSessionRepository) {
this.myUserDetailService = myUserDetailService;
this.dataSource = dataSource;
this.findByIndexNameSessionRepository = findByIndexNameSessionRepository;
}
/**
* 创建用来将session共享到redis中的bean
* @return
*/
@Bean
SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry(){
return new SpringSessionBackedSessionRegistry(findByIndexNameSessionRepository);
}
最后还需要在configure
方法里面配置
.sessionRegistry(springSessionBackedSessionRegistry());
我们登录前后查看redis即可,可以看到这里把session信息存储到了redis当中了。