SpringBoot+Session+自定义拦截器实现 异地登录 下线

前言

最近在开发系统的时候发现有一个bug,在账号登录成功了以后!再打开一个浏览器登录发现两个都能登录这就使我们的系统安全性大大降低!!

什么是异地登录?

好比qq,王者登录一样,同一个账号在不同设备只能登录一次,前一个会被挤下线

流程

1,前端发起请求登录校验成功后,将当前用户信息存到session中,将当前session会话存储在一个map容器中,然后返回提示消息给前台

2,再次发起登录请求,判断当前map容器是否存在当前的session;如果存在则过期上一个session,存储当前登录会话信息到map容器中

3,再次访问第一个请求,通过拦截器判断当前session 是否有用户登录,有则放行;没有则提示下线用户

代码

controller

    private final Map<String,HttpSession> sessionMap = new HashMap<>();

    @ApiOperation("用户登录")
    @PostMapping("/userLogin")
    public Result<Integer> userLogin(User user, HttpSession session) {
        log.info("登录用户:{}", user);
        User login = userService.login(user);
        if (login == null || !user.getPwd().equals(login.getPwd())) {
            return Result.error("用户名或密码错误");
        }
        if (Objects.equals("普通用户", user.getType()) && !Objects.equals(user.getType(), login.getType())) {
            return Result.error("该角色不存在!");
        }
        // 存储会话
        if (!sessionMap.isEmpty()) {
            // 判断是否登录过
            if (sessionMap.containsKey(login.getUserId().toString())) {
                // 过期上一个session
                sessionMap.get(login.getUserId().toString()).invalidate();
                sessionMap.remove(login.getUserId().toString());
            }
        }
        session.setMaxInactiveInterval(30 * 60);
        session.setAttribute("user", login);
        session.setAttribute(login.getUserId().toString(), login);
        sessionMap.put(login.getUserId().toString(), session);
        return Result.success("登录成功", login.getUserId());
    }

    @GetMapping("/getUserInfo/{userId}")
    public Object getUserLoginInfo(@PathVariable("userId") String userId) {
       HttpSession session = sessionMap.get(userId);
        try {
            User user = (User) session.getAttribute(userId);
            log.info("当前用户:" + user);
            return user;
        }catch (NullPointerException e) {
            throw new ServiceException(Constants.CODE_NOT_FORBIDDEN,"登录失效");
        }
    }

interceptor

package net.ltbk.music.common;

import lombok.extern.slf4j.Slf4j;
import net.ltbk.music.bean.User;
import net.ltbk.music.common.exception.ServiceException;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @Program: music
 * @ClassName LoginIntercepter
 * @Author: liutao
 * @Description:
 * @Create: 2023-10-18 23:04
 * @Version 1.0
 **/

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        User user= (User) session.getAttribute("user");
        String uri = request.getRequestURI();
        log.info("请求地址:{}",uri);
        log.info("登录用户:{}",user);
        if (user != null) {
            return true;
        }else {
            throw new ServiceException(Constants.CODE_NOT_FORBIDDEN,"用户已下线");
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

 千万别忘了放行 登录接口哦

registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/","/login","/register","/user/userLogin","/user/register","/user/logout")

如何配置全局异常SpringBoot整合Validation统一结果封装和全局异常捕获和参数校验_晚上睡不着!的博客-CSDN博客相信大家都用过hibernate-validation 的校验工具,对我们参数校验的工具。https://blog.csdn.net/LT19990304/article/details/132913072?spm=1001.2014.3001.5501效果图

打开一个chrome登录并访问

打开edge浏览器登录相同账号

刷新chrome浏览器

结尾

 到这里我们今天的学习就结束啦!!

欢迎点赞,关注,收藏三连!!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚上睡不着!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值