码迷,mamicode.com
首页 > 编程语言 > 详细

SpringBoot 整合 redis 实现 token 验证

时间:2021-05-03 12:03:59      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:===   错误   random   framework   timeout   连接超时   jedis   tst   存在   

SpringBoot 整合 redis 实现 token 验证

在上一节中,实现了 SpringBoot + redis 的整合,因此在这里只列出必要部分的 redis 代码。

1、Redis 依赖

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、Redis 配置

2.1、properties 文件配置:

spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=123456
# 数据库索引(默认为0)
spring.redis.database=15
#最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=100
#最大空闲连接
spring.redis.jedis.pool.max-idle=8
#最小空闲连接
spring.redis.jedis.pool.min-idle=0
#最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=60000
#连接超时时间
spring.redis.timeout=1000

2.2、自定义配置类 RedisConfig

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
        //创建RedisTemplate<String,Object>对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //配置连接工厂
        template.setConnectionFactory(factory);
        //定义Jackson2JsonRedisSerializer序列化对象
        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        //指定要序列化的域,field,get和set,以及修饰符范围,ANY是包括private到public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //指定序列化输入的类型,类必须是非final修饰的,final修饰的类如String,Integer会报异常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jsonRedisSerializer.setObjectMapper(objectMapper);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 值采用json序列化
        template.setValueSerializer(jsonRedisSerializer);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

2.3、redis 工具类 RedisUtils

@Component
public class RedisUtils {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 指定缓存失效时间
     *
     * @param key      键
     * @param time     时间
     * @param timeUnit 时间单位
     * @return
     */
    public boolean expire(String key, long time, TimeUnit timeUnit) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
     /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    //============================String=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key      键
     * @param value    值
     * @param time     时间 time要大于0 如果time小于等于0 将设置无限期
     * @param timeUnit 时间单位
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, timeUnit);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

3、登录接口生成 token

@GetMapping(value = "/tokenLogin")
@ResponseBody
public Result tokenLogin(String name, String password) {
    User user = userService.getOne(new QueryWrapper<User>().eq("name", name));
    if (user == null) {
        return ResultUtil.fail(1, "账号未注册");
    } else {
        //MD5加密
        String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!md5Password.equals(user.getPassword())) {
            return ResultUtil.fail(2, "密码错误");
        }
    }
    //生成token
    String token = UUID.randomUUID().toString().replaceAll("-", "");
    //保存token,key为token,value为id,有效期为1个小时
    redisUtils.set(token, user.getId(), 1, TimeUnit.HOURS);
    return ResultUtil.success(token);
}

4、过滤器验证 token

public class AccessFilter implements Filter {
    Logger logger = LoggerFactory.getLogger(AccessFilter.class);

    private RedisUtils redisUtils;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //非Spring管理环境,需要手动注入Bean
        redisUtils = SpringUtils.getBean(RedisUtils.class);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //登录接口跳过验证
        if (request.getRequestURI().contains("/tokenLogin")) {
            filterChain.doFilter(request, response);
            return;
        }

        /** token+redis验证 */
        String token = request.getHeader("token");
        if (!redisUtils.hasKey(token)) {
            logger.info("token过期,请重新登录");
            return;
        }
        //刷新token有效期
        redisUtils.expire(token, 1, TimeUnit.HOURS);
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

5、登出清除 token

@GetMapping(value = "/tokenLogout")
@ResponseBody
public Result tokenLogout(HttpServletRequest request) {
    String token = request.getHeader("token");
    //删除redis的token
    redisUtils.del(token);
    return ResultUtil.success(0,"退出成功");
}

SpringBoot 整合 redis 实现 token 验证

标签:===   错误   random   framework   timeout   连接超时   jedis   tst   存在   

原文地址:https://www.cnblogs.com/CF1314/p/14722989.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!