springboot 使用redis 实现token自动存储和设定过期时间

使用场景:用户登录系统后,一定时间不使用后,再访问相关接口提示用户  此session已经过期,请重新登录

功能大致流程: 首先用户登录成功后,在redis添加一条缓存并设置一个有效时间,标识这个用户登录过系统了。

然后访问其他接口时,添加一个拦截器,获取Header的token是否存在,是否失效。如果没有问题就更新下redis的这条缓存防止他过期。然后调用到接口

比如:我这里调用一个登录接口:"user/login" 接口 登录成功后,将token存到redis里,然后将 token 返回给前台,让他每次再访问我的接口时都要在请求头里使用token,然后再用另一个接口校验token是否过期 “/test” 。

大致流程就是这样,下面是部分代码

## pom中引入相关依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>nl.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.6</version>
        </dependency>

## 项目接口

## 部分代码

------------------------------------ AuthInterceptor ------------------------------------
package com.example.demo_2.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.example.demo_2.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

public class AuthInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisService redisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            JSONObject result  = new JSONObject();
            result.put("returnCode",10001);
            result.put("returnMsg","用户未登录,请登录后操作!");
            return false;
        }
        Object loginStatus = redisService.get(token);
        if( Objects.isNull(loginStatus)){
            JSONObject result  = new JSONObject();
            result.put("returnCode",10002);
            result.put("returnMsg","此session已经过期,请重新登录");
            response.getWriter().print(result);
            return false;
        }
        redisService.update(token);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
------------------------------------- AuthConfig -------------------------------------
package com.example.demo_2.config;

import com.example.demo_2.Interceptor.AuthInterceptor;
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;



@Configuration
public class AuthConfig implements WebMvcConfigurer {
    @Bean
    public AuthInterceptor initAuthInterceptor(){
        return new AuthInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //addPathPatterns:哪些路径下的会被拦截
        //excludePathPatterns:哪些路径下不会被拦截
        registry.addInterceptor(initAuthInterceptor()).addPathPatterns("/test/**").excludePathPatterns("/user/**");
    }
}
------------------------------------- RedisService -------------------------------------
package com.example.demo_2.service;

public interface RedisService {

    void set(String key, Object value);

    Boolean delete(String key);

    Boolean update(String key);

    Object get(String key);

}

----------------------------------- RedisServiceImpl -------------------------------------
package com.example.demo_2.service.impl;

import com.example.demo_2.service.RedisService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements RedisService {
    @Resource
    private RedisTemplate redisTemplate;

    /*
     * 设置key并且设置有效时间
     * */
    public void set(String key, Object value) {
        //更改在redis里面查看key编码问题
        RedisSerializer redisSerializer =new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        ValueOperations<String,Object> vo = redisTemplate.opsForValue();
        vo.set(key, value,2,TimeUnit.MINUTES);//设置key并且设置有效时间
    }
    /*
    * 删除key
    * */
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }
    /*
     * 更新key
     * */
    public  Boolean update(String key){

        return redisTemplate.expire(key, 2, TimeUnit.MINUTES);
    }
    /*
     * 查询key
     * */
    public Object get(String key) {
        ValueOperations<String,Object> vo = redisTemplate.opsForValue();
        return vo.get(key);
    }
}

----------------------------------- UserService ------------------------------------
package com.example.demo_2.service;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Service
public interface UserService {

    JSONObject login(Map<String,Object> mapParam);

    JSONObject logout(HttpServletRequest request);
}

----------------------------------- UserServiceImpl ------------------------------------
package com.example.demo_2.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.demo_2.service.RedisService;
import com.example.demo_2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.example.demo_2.utils.md5.MD5Utils.MD5String;
import static org.springframework.util.StringUtils.isEmpty;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private RedisService redisService;

    public JSONObject login(Map<String, Object> mapParam) {
        JSONObject result = new JSONObject();

        if (isEmpty(mapParam.get("username"))) {
            result.put("resultCode", 10001);
            result.put("resultMsg", "用户名不能为空!");
            return result;
        }
        if (isEmpty(mapParam.get("password"))) {
            result.put("resultCode", 10001);
            result.put("resultMsg", "密码不能为空!");
            return result;
        }
        String username = mapParam.get("username").toString();
        String password = mapParam.get("password").toString();

        if (Objects.equals("ghc", username) && Objects.equals("123", password)) { // 这里应该去数据库查询数据然后比对我这里就直接写死了
            String token = username + "_" + UUID.randomUUID().toString();
            String strMd5 = MD5String(token); // 象征性的加个密
            redisService.set(strMd5, username); //写入redis set方法里设置里存在时间
            Map<String, Object> map = new HashMap<>(); // 可以设置一些登录人信息
            map.put("userid", 1);
            map.put("username", username);
            map.put("password", password);
            map.put("cosNum", "998");
            map.put("token", strMd5);
            result.put("resultCode", 10000);
            result.put("resultMsg", "登录成功!");
            result.put("resultData", map);
        } else {
            result.put("resultCode", 10001);
            result.put("resultMsg", "登录失败!");
            result.put("resultData", "");
        }
        return result;
    }

    public JSONObject logout(HttpServletRequest request) {
        JSONObject result = new JSONObject();
        String token = request.getHeader("token");
        Boolean delete = redisService.delete(token);
        if (!delete) {
            result.put("resultCode", 10001);
            result.put("resultMsg", "注销失败,请检查是否登录!");
            result.put("resultData", "");
        } else {

            result.put("resultCode", 10000);
            result.put("resultMsg", "注销成功!");
            result.put("resultData", "");
        }
        return result;
    }
}

----------------------------------- UserController ------------------------------------
package com.example.demo_2.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.demo_2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/login")
    public JSONObject login(@RequestParam Map<String, Object> map) {
        return userService.login(map);
    }

    @GetMapping("/logout")
    public JSONObject logout(HttpServletRequest request) {
        return userService.logout(request);
    }
}

----------------------------------- TestController ------------------------------------
package com.example.demo_2.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping("/getTest")
    public String getTest() {
        return "getTest通过token登录成功了";
    }

    @GetMapping("/getTest1")
    public String getTest1() {
        return "getTest1方法通过token登录成功了";
    }
}

---------------------------------- StudentController ------------------------------------
package com.example.demo_2.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/student")
public class StudentController {
    @GetMapping("/getTest")
    public String getTest() {
        return "getTest没有使用到拦截器";
    }
}

如果对你有用请点个赞 再走呗!!

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
首先,你需要在 Spring Boot 项目中添加 Redis 和 Spring Mail 的依赖。 ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> ``` 然后,你需要在 application.properties 文件中配置 Redis 和 Mail 相关的属性。 ``` # Redis spring.redis.host=127.0.0.1 spring.redis.port=6379 # Mail spring.mail.host=smtp.gmail.com spring.mail.port=587 spring.mail.username=your-email@gmail.com spring.mail.password=your-email-password spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true ``` 接着,你需要创建一个 Redis 队列,用于存储待发送邮件的信息。可以使用 RedisTemplate 来操作 Redis 队列。 ``` @Autowired private RedisTemplate<String, Object> redisTemplate; public void sendEmail(String to, String subject, String content) { Email email = new Email(to, subject, content); redisTemplate.opsForList().leftPush("email_queue", email); } ``` 最后,你需要创建一个定时任务,从 Redis 队列中取出邮件信息,并使用 JavaMailSender 发送邮件。 ``` @Autowired private JavaMailSender javaMailSender; @Scheduled(fixedDelay = 1000) public void sendEmailFromQueue() { Email email = (Email) redisTemplate.opsForList().rightPop("email_queue"); if (email != null) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email.getTo()); message.setSubject(email.getSubject()); message.setText(email.getContent()); javaMailSender.send(message); } } public class Email { private String to; private String subject; private String content; public Email(String to, String subject, String content) { this.to = to; this.subject = subject; this.content = content; } // getters and setters } ``` 这样,你就可以使用 Redis 自动发送邮件了。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值