欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-03 09:54:01
1.springbootWeb项目引包 org.springframework.boot spring-boot-starter-data-redis ....

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