springSecurity2.7.9 实现“用户在另外一台电脑登录,您已被下线“的效果

首先确保springSecurity的版本是2.7.9

第一步:配置filterChain()方法

java 复制代码
				.and()
                .sessionManagement()
                // 设置一个session最多只能有一个用户使用,默认是无限制
                .maximumSessions(1)
                .sessionRegistry(sessionRegistry)
                .expiredSessionStrategy(sessionInformationExpiredStrategy);

.maximumSessions(1): 设置一个会话最多只能有一个用户使用。这意味着当一个用户已经登录并且会话尚未过期时,如果另一个用户尝试使用相同的凭据登录,先前的会话将被失效。

.sessionRegistry(sessionRegistry): 设置一个用于跟踪活动会话的SessionRegistry对象。SessionRegistry用于管理和访问当前活动会话的信息。

java 复制代码
    @Resource
    private SessionRegistry sessionRegistry;

.expiredSessionStrategy(sessionInformationExpiredStrategy): 设置一个会话过期策略。当会话过期时,将采取特定的操作。sessionInformationExpiredStrategy是一个实现了SessionInformationExpiredStrategy接口的自定义策略对象,用于定义会话过期后的处理逻辑。

通过以上配置,可以实现对会话的最大并发控制和会话过期处理.

第二步:重写SessionInformationExpiredStrategy中的onExpiredSessionDetected方法,自定义会话过期策略

java 复制代码
public class MySessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {

    private static final Logger logger = LogManager.getLogger(MySessionInformationExpiredStrategy.class);

    @Resource
    AuthenticationFailureHandlerImp authenticationFailureHandlerImp;

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) {
        // 1. 获取用户名
        UserDetails userDetails = (UserDetails) event.getSessionInformation().getPrincipal();
        AuthenticationException exception = new AuthenticationServiceException(
                String.format("[%s]用户在另外一台电脑登录,您已被下线", userDetails.getUsername()));
        try {
            // 当用户在另外一台电脑登录后,交给失败处理器回到认证页面
            event.getRequest().setAttribute("toAuthentication" , true);
            authenticationFailureHandlerImp.onAuthenticationFailure(event.getRequest(),event.getResponse(),exception);
        }catch (Exception e){
            logger.error("MySessionInformationExpiredStrategy->onExpiredSessionDetected:{}", e.getMessage());
        }
    }


}

第三步:把SessionRegistry和SessionInformationExpiredStrategy注册到springboot中交由springboot管理

java 复制代码
@Configuration
public class Config {

    @Bean
    @ConditionalOnMissingBean(SessionInformationExpiredStrategy.class)
    public SessionInformationExpiredStrategy informationExpiredStrategy() {
        return new MySessionInformationExpiredStrategy();
    }

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

第四步:在AuthenticationFailureHandler方法定义一下,springSecurity的登录失败回调方法

我是这样写的,比较粗糙

java 复制代码
@Component
public class AuthenticationFailureHandlerImp implements AuthenticationFailureHandler {
    private static final Logger logger = LogManager.getLogger(AuthenticationFailureHandlerImp.class);
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response
            , AuthenticationException exception) throws IOException, ServletException {
            response.setContentType("application/json;charset=utf-8");
        if (exception.getMessage().indexOf("您已被下线") !=0) {
            response.setStatus(400);
            response.getWriter().append(ResponseStatus.createFailureStatus(exception.getMessage()).toString());
        }else {
            response.setStatus(403);
            response.getWriter().append(ResponseStatus.createFailureStatus("登录失败").toString());
        }
        logger.error("AuthenticationFailureHandlerImp: {}", exception.getMessage());
    }
}

结束:
A用户在A电脑上登录,之后A用户又在B电脑上登录,这个时候,A电脑在去访问我们的后端接口就会提示"A用户在另外一台电脑登录,您已被下线",还没有做到实时通知,感兴趣的可以自己实现一下

相关推荐
Joe_Wang58 分钟前
【从0到1学习JVM · 15】对象在堆里来回倒腾,究竟怎样才会进老年代?
java·jvm·学习·垃圾回收
一条小小yu21 分钟前
为什么使用springboot
java·spring boot·后端
Elastic 中国社区官方博客28 分钟前
Kubernetes attributes processor v1:它对 EDOT Collector 意味着什么
java·大数据·elasticsearch·搜索引擎·贪心算法·kubernetes·全文检索
Sarvartha33 分钟前
对象创建与引用
java·开发语言
大侠归来1 小时前
C语言与C++在基础语法上的区别
java·c语言·c++
小宋10212 小时前
SQL + RAG 混合问答实战:结构化指标与文档证据如何统一路由
java·jvm·人工智能·sql
bro_Java6662 小时前
链表进阶2:双向链表的构建
java·数据结构·链表
DianSan_ERP2 小时前
多平台订单自动下载与回传的技术实现:从消息推送到状态闭环引言
java·linux·服务器·前端·网络·架构·自动化
Joe_Wang52 小时前
【从0到1学习JVM · 13】点进JDK源码只有一个分号?搞懂本地方法栈与JNI机制
java·jvm·学习·本地方法栈
AI 算法大模型备案~当当2 小时前
各地备案数量怎么看:一份属地公告的认读与台账方法
java·数据库·人工智能