springboot+redis+session相同用户只能登陆一次,前者会被挤下线(类似QQ)

2022-07-24,,,,

1.springbootWeb项目

  • 引包
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
  • .yml文件配置redis信息
#redis配置信息
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    jedis:
      pool:
        max-active: 8
        max-idle: 500
        max-wait: -1
        min-idle: 0
    lettuce:
      shutdown-timeout: 0

2.项目登录接口


 @Autowired
 private RedisTemplate<String,String> redisTemplate;

    @ApiOperation(value = "登录")
    @PostMapping(value = "/login")
    public RestResult<DatagoUser> login(@RequestBody DatagoUser datagoUser, HttpServletRequest request) {

        String kl = MD5andKL.KL(datagoUser.getPassword());
        datagoUser.setPassword(kl);
        datagoUser = datagoUserService.login(datagoUser);
        if (datagoUser != null) {
            if (datagoUser.getStatus().equals(true)) {
                DatagoRole datagoRole = roleService.selectByRole(datagoUser.getRoleId());
                datagoUser.setType(datagoRole.getType());
                datagoUser.setLastLoginTime(new Date());
                datagoUser.setLastLoginIp(UserContext.getIp2());
                datagoUser.setSessionId(request.getRequestedSessionId());
                datagoUserService.updateByPrimaryKeySelective(datagoUser);
//                UserContext.setUser(datagoUser);

				//主要核心代码
                request.getSession().setAttribute("user",datagoUser.getId());
                redisTemplate.opsForValue().set(datagoUser.getId(),request.getSession().getId());

                return RestResultUtil.genSuccessResult(datagoUser);
            } else {
                return RestResultUtil.failed("用户被禁用,请联系管理员!!!");
            }
        } else {
            return RestResultUtil.failed("用户密码异常,请重新输入!!!");
        }
    }

3.拦截器(2个类)

package com.datago.robot.common.interceptor;

import com.datago.robot.common.utils.RestResult;
import com.datago.robot.common.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * @author HB
 */
@Component
@Slf4j
public class LoginHandlerInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 1.在调用控制器方法前,拦截
     * <p>
     * 返回值为false,代表拦截
     * 返回值为true,代表放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("---------------------开始进入请求地址拦截----------------------------");
        //注释掉为了swagger-ui接口测试可以正常使用
//        DatagoUser user = (DatagoUser) UserContext.getSession().getAttribute("user");
        String user = (String) request.getSession().getAttribute("user");
        RestResult restResult = new RestResult();
        if (Utils.isNotEmpty(user)) {
            //检测redis中是否含有sessionId
            String loginSessionId = redisTemplate.opsForValue().get(request.getSession().getAttribute("user"));
            if (loginSessionId != null && loginSessionId.equals(request.getSession().getId())) {
                return true;
            } else {
                restResult.setMessage("该账号在另一台设备上登录,您被强制下线,请您重新登陆!!!");
            }
        } else {
            restResult.setMessage("请您先进行登录");
        }
        restResult.setCode(-2);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(JSONObject.fromObject(restResult).toString());
        return false;
    }

    /**
     * 2.在调用控制器方法后,拦截(在生成视图之前)
     */
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("=============进入拦截器了,请求处理后,渲染ModelAndView前调用。=================================");
        // TODO Auto-generated method stub
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }


    /**
     * 3.在视图生成之后(后台所有所有逻辑都完成后)
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("=============进入拦截器了,渲染ModelAndView后调用。=================================");
        // TODO Auto-generated method stub
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }


}

package com.datago.robot.common.interceptor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


/**
 * @ProjectName powerFind
 * @Package com.datago.robot.common.config
 * @Name WebConfigurer
 * @Author HB
 * @Date 2021/2/18 10:20
 * @Version 1.0
 */
@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    LoginHandlerInterceptor loginInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // TODO Auto-generated method stub
        // addPathPatterns("/**") 表示拦截所有的请求,
        // excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/",
                        //登录接口
                        "/datagoUser/login",
                        //导出报名人员excel文件接口
                        "/file/**",
                        //展示活动照片接口
                        "/activityImage/**",

                        "/activity/getIsActivityCount",
                        "/activity/getActivityCount",
                        "/image/imageFileSave",
                        "/activity/importShowTemplate",
                        "/activity/templatePersonDownload",
                        "/honor/importShowTemplate",
                        "/honor/templatePersonDownload"
                );
    }

}

4.写的有点。。。,欢迎留言一同探讨学习。
5.要想拿来自己用必须要修改业务逻辑代码,方可使用;楼主比较懒,就直接拷贝来了,不喜么怪。。。。
6.最后再共享下,redis资源(也可在博主资源下载中进行下载)

  • 博主CSDN资源
https://download.csdn.net/download/sinat_37239798/15542982
  • 博主百度网盘资源
链接:https://pan.baidu.com/s/1Uh6fsriyGpb8xDwx94ew7g 
提取码:1234 
复制这段内容后打开百度网盘手机App,操作更方便哦

本文地址:https://blog.csdn.net/sinat_37239798/article/details/114304314

《springboot+redis+session相同用户只能登陆一次,前者会被挤下线(类似QQ).doc》

下载本文的Word格式文档,以方便收藏与打印。