使用session实现单用户多端登录限制

news2024/9/20 16:54:13

基本流程:

首先获得当前浏览器访问服务器的session,然后根据用户的信息(如id等)在redis中查找,如果找到,并且和查找对应的session不同,则可以判断已经有其他设备登录过了,这个时候就可以把redis中对应用户的session替换为当前的session,这个时候就代表其他设备的用户被强制下线了,当前设备成功登录。

下面是核心代码实现:      

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/")
    public String index(HttpServletRequest request){
        String sessionId= request.getSession().getId();
        User user;
        // 找到了sessionId,并且在对象里存储着,说明是同一设备
        if ((user=userService.isContainedInRedis(sessionId))!=null) {
            request.setAttribute("user",user);
            return "index.html";
        }
        return "login.html";
    }
    // 这里直接使用postman进行输入了
    @PostMapping("/login")
    public String login(@RequestParam("username") String username,HttpServletRequest request){
        User user=userService.isSameDeviceAndDownload(username, request.getSession().getId());
        request.setAttribute("user",user);
        return "index.html";
    }
    // 这里直接使用postman进行输入了
    @PostMapping("/register")
    public void register(@RequestParam("username") String username,@RequestParam("name") String name,HttpServletRequest request) throws JsonProcessingException {
        User user = new User(username,name, request.getSession().getId());
        userService.store(user);
    }
}
@Service
public class UserService {
    @Autowired
    private RedisTemplate redisTemplate;
    // 判断sessionId是否存在于redis中,如果存在,说明登录过了,用户可以直接登录
    public User isContainedInRedis(String sessionId)  {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<Object,Object> users = redisTemplate.opsForHash().entries("user");
        System.out.println(users.size());
        for (Map.Entry<Object, Object> entry : users.entrySet()) {
            try {
                User user = objectMapper.readValue((String) entry.getValue(), User.class);
                if(user.getSessionId().equals(sessionId)){
                    return user;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    // 存储user对象
    public void store(User user) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println(user);
        redisTemplate.opsForHash().put("user",user.getUsername(),objectMapper.writeValueAsString(user));
    }
    // 判断是否是同一设备,否则将其下线
    public User isSameDeviceAndDownload(String username,String sessionId) {
        System.out.println("username:"+username);
        Object user = redisTemplate.opsForHash().get("user", username);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user1 = objectMapper.readValue((String) user, User.class);
            //说明不是同一设备
            if(!user1.getSessionId().equals(sessionId)){
                user1.setSessionId(sessionId);
                redisTemplate.opsForHash().put("user",username,objectMapper.writeValueAsString(user1));
            }
            return user1;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

如果当我们首次访问系统时,此时redis中是没有存放我们的sessionId值的

这时就会出现以下情况:

 接下来我们先手动注册一个账户:

然后观察redis:

 

这时,我们用另一个设备进行(这里使用postman可以达到同样的效果)登录:

         

 可以看到成功登录。

此时的sessionId也被改变了,另一个用户将会被强制下线 

灵感来源:【实践】使用session实现单用户多端登录限制-腾讯云开发者社区-腾讯云

项目代码地址:https://github.com/hanxuyyds/SingleUserMultiLoginRestrictionApplication

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2099015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Andorid 如何查看某个.so库的依赖

Android 手机中&#xff0c;如何查看其中某个.so 库依赖了其它哪些库&#xff1f;1.方法&#xff1a;使用android 手机中的readelf 命令.。2. 操作步骤&#xff1a;如查看libdolphin.so 的的依赖。 &#xff08;1&#xff09;adb shell 进入手机&#xff0c;进入libdolphin.so…

C++学习笔记----6、内存管理(一)---- 使用动态内存(2)

2.2、我的好朋友malloc怎么样了&#xff1f; 如果你是一个C程序员&#xff0c;对啦&#xff0c;我就是&#xff0c;你可能会想&#xff0c;malloc()函数怎么样了。在C语言中&#xff0c;malloc()用于分配一定数量的内存字节。总的来讲&#xff0c;使用malloc()简单直接。在C中m…

传统CV算法——图像特征算法之角点检测算法

文章目录 2. 角点检测2.1 角点概述2.1.1 概念2.1.2 角点的特点2.1.3 角点的检测2.1.4 角点的应用 2.2 角点检测算法2.2.1 Harris 角点2.2.1.1 Harris 角点介绍2.2.1.2 Harris计算流程1. 图像梯度2. 结构张量3. Harris响应函数4. 非极大值抑制5. 阈值化 2.2.1.3 Harris性质1. 旋…

《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层(4)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层&#xff08;3&#xff09; 7.1 数据链路层的组成结构 7.1.1 数据链路层的状态 数据链路层需要通过物理层监控PCIe链路的状态&#xff0c;并维护数据链路层的“控制与…

厂房电气火灾现场勘验要点

0前言 随着我国社会的发展&#xff0c;电气化水平提升&#xff0c;但随之而来的是频繁的电气火灾事故&#xff0c;对生活和生产造成重大危害。电气火灾是最常见的火灾类型&#xff0c;通常由电路短路、电压过高、电阻过大或电路超负荷引起&#xff0c;这些因素都可能导致火花并…

电脑怎么录屏?探索电脑录屏工具,三款高效工具推荐及使用指南

在数字化时代&#xff0c;电脑录屏已成为日常工作和学习中不可或缺的一部分。无论是制作教程、记录会议还是捕捉游戏精彩瞬间&#xff0c;一个好的录屏工具都能让这一切变得简单高效。今天&#xff0c;我们将为您介绍三款备受推崇的录屏软件&#xff1a;Windows自带的步骤记录器…

面向对象程序设计之链表 list 的简析(C++)

简介&#xff1a;链表是一个双向的结构&#xff0c;与string与vector不同的是他不支持[]访问&#xff0c;因为链表是由一个节点一个节点连接而成的&#xff0c;并不连续。我们可以在常数量级内对于链表进行插入与删除数据 1.构造函数 我们在cplusplus.com中可以查到链表总共有四…

无人机遥控器的材料组成!!!

1. 外壳 材料&#xff1a;遥控器外壳通常采用高强度塑料&#xff08;如ABS、PC等&#xff09;或轻质金属&#xff08;如铝合金&#xff09;制成。这些材料具有良好的抗冲击性、耐磨性和一定的耐腐蚀性&#xff0c;能够保护内部电子元件免受外界环境的影响。 特点&#xff1a;…

智能优化算法-秃鹰优化算法(BES)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍&#xff1a; 秃鹰搜索算法‌&#xff0c;它是一种基于自然界中秃鹰觅食行为启发的优化算法&#xff0c;旨在解决优化问题。该算法模仿了秃鹰在寻找猎物时的策略&#xff0c;结合了随机搜索和逐步优化的特点&#…

AGI系列(9)手把手带你玩转 Coze 画板节点

本文以智能体“日签卡片生成器”的制作来阐述 Coze 画板节点的使用方法。 效果演示 核心流程 日签卡片生成器工作流整体分为两部分&#xff1a; 工作流&#xff1a;其核心流程为通过用户输入的主题词生成卡片的标题、内容 图像流&#xff1a;通过LLM输出的内容在图像流完成卡…

【C++ Primer Plus习题】9.3

问题: 解答: #include <iostream> using namespace std;struct chaff {char dross[20];int slag; };int set_chaff(chaff& f, char* c, int n) {if (strlen(c) > 0){strcpy_s(f.dross, c);f.slag n;return 1;}return 0;}void show_cahff(const chaff& f) {c…

rabbitmq高可用集群搭建

需求分析基本情况 在进行RabbitMQ搭建时&#xff0c;我们基于现有的连接数据和业务需求进行了深入分析。目前的统计数据显示&#xff0c;连接数为631&#xff0c;队列数为80418。为了确保业务需求的顺利满足&#xff0c;我们需要在云产品和自建RabbitMQ消息队列服务之间做出选…

最新软件测试面试题,常见面试题及答案汇总,不怕拿不到offer

面试题包括以下十六个模块&#xff1a;软件测试基础&#xff0c;liunx基础&#xff0c;MySQL基础&#xff0c;web测试&#xff0c;APP测试&#xff0c;性能测试&#xff0c;selenium&#xff0c;Python基础&#xff0c;接口测试&#xff0c;lordrunner&#xff0c;计算机网络&a…

chapter11-枚举和注解——(注解)——day14

目录 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、JmalCloud介绍2.1 JmalCloud简介2.2 JmalCloud优点2.3 JmalCloud使…

Android Camera系列(一):SurfaceView+Camera

心行慈善&#xff0c;何需努力看经—《西游记》 本系列主要讲述Android开发中Camera的相关操作、预览方式、视频录制等&#xff0c;项目结构代码耦合性低&#xff0c;旨在帮助大家能从中有所收获&#xff08;方便copy :&#xff09; &#xff09;&#xff0c;对于个人来说也是一…

【Next】2. 项目构建

打开 Next.js 的官方文档&#xff1a;https://nextjs.org/docs/getting-started/installation&#xff08;国内文档不够新&#xff09; Next.js 版本 14.2 &#xff0c; Node.js 的版本要求必须 > 18.18。 Next 有两种开发模式&#xff0c;下面讲新的 APP Router。 创建项…

VS2022 C++ 控制台中文乱码解决方案

最近写读文件的代码时&#xff0c;遇到了VS控制台读取中文时出现乱码&#xff0c;看了网上主要有两种方法 &#xff1a; 1、在VS菜单栏里点击"文件"选项&#xff0c;然后选择"高级保存选项"来设置文件格式&#xff0c;但是我的文件选项里没有"高级保存…

COT报告:美国期货市场持仓情况分析

市场情绪的晴雨表 COT报告揭示了美国期货市场中不同参与者的持仓情况&#xff0c;尤其是净多头和净空头头寸。这份报告发布时会有约三天的滞后&#xff0c;因此提供的是过往数据。通常&#xff0c;该报告在星期五发布&#xff0c;反映的是截至前一星期二的数据&#xff0c;因此…

蓝牙地址BD Addr烧录

关于蓝牙地址,有很多文章有介绍,主要要知道下面一个图: 蓝牙设备地址(或BD_ADDR)是制造商分配给每个蓝牙设备的唯一48位标识符。蓝牙地址通常显示为以十六进制书写的6个字节,用冒号分隔(例如-00:11:22:FF:EE)。蓝牙地址的上半部分(最重要的24位)被称为组织唯一标识符…