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

基本流程:

首先获得当前浏览器访问服务器的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

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值