Redis实现一个账号只能登录一个设备


Posted in Redis onApril 19, 2022

在有些场景下,我们希望用户一个账号只能登录一个设备。

这个时候我们可以用Redis来实现。

原理: 用户首次登录时,将用户信息存入Redis,key是用户id,value是token。当用户在其他设备登录时,会重新生成token,这个时候原先的token已经被覆盖了。所以用户在访问需要登录账号的操作时,系统会拦截请求判断token是否存在。当然是不存在的,所以我们就实现了单个设备登录的需求。

这里只提供大概的样例。

用户登录

@PostMapping("login")
@ApiOperation(value = "用户登录",notes = "用户登录")
public GraceJSONResult login(@RequestParam String userId,HttpServletRequest request) throws Exception {
    String uToken = UUID.randomUUID().toString();
    //把token存入redis
    redis.set("redis_user_token"+":"+userId,uToken);
    //返回用户信息,包含token
    return GraceJSONResult.ok(usersVO);
}

拦截器

拦截哪些操作需要用户登录,在拦截器中实现单设备登录。

说明:BaseInfoProperties是共有的代码,集成这个类就可以直接使用reidis。

public class BaseInfoProperties {
    @Autowired
    public RedisOperator redis;
}

说明:GraceException是自定义的抛出异常的类,这里不做展示。

public class UserTokenInterceptor extends BaseInfoProperties implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String userId = request.getHeader("headerUserId");
        String userToken = request.getHeader("headerUserToken");
        // 判断用户id和token是否为空
        if(StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)){
            String redisToken=redis.get(REDIS_USER_TOKEN+":"+userId);
            //判断token是否失效
            if(StringUtils.isBlank(redisToken)){
                GraceException.display(ResponseStatusEnum.UN_LOGIN);
                return false;
            }else {
                //判断token是否一致,如果不一致,表示用户在别的手机端登录,token被覆盖了
                if(!redisToken.equalsIgnoreCase(redisToken)){
                    GraceException.display(ResponseStatusEnum.TICKET_INVALID);
                    return false;
                }
            }
        }else {
            // 用户id和token为空
            GraceException.display(ResponseStatusEnum.UN_LOGIN);
            return false;
        }

        return true;
    }
}

注册拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer{
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //要拦截的请求,哪些需要登录
        registry.addInterceptor(userTokenInterceptor())
                .addPathPatterns("/userInfo/modifyUserInfo")
                .addPathPatterns("/userInfo/modifyImage");
    }
    //用户未登录拦截器
    @Bean
    public UserTokenInterceptor userTokenInterceptor() {
       return  new UserTokenInterceptor();
    }
}

到此这篇关于Redis实现单设备登录的文章就介绍到这了!

Redis 相关文章推荐
Redis主从配置和底层实现原理解析(实战记录)
Jun 30 Redis
Redis 常见使用场景
Aug 30 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 Redis
详解redis在微服务领域的贡献
Oct 16 Redis
Redis模仿手机验证码发送的实现示例
Nov 02 Redis
关于SpringBoot 使用 Redis 分布式锁解决并发问题
Nov 17 Redis
聊聊redis-dump工具安装问题
Jan 18 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
redis击穿 雪崩 穿透超详细解决方案梳理
Mar 17 Redis
Redis官方可视化工具RedisInsight安装使用教程
Apr 19 Redis
Redis主从复制操作和配置详情
Sep 23 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 #Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
You might like
php下批量挂马和批量清马代码
2011/02/27 PHP
PHP临时文件的安全性分析
2014/07/04 PHP
PHP大批量插入数据库的3种方法和速度对比
2014/07/08 PHP
php提高网站效率的技巧
2015/09/29 PHP
利用PHP命令行模式采集股票趋势信息
2016/08/09 PHP
php 输出缓冲 Output Control用法实例详解
2020/03/03 PHP
JavaScript Event学习第六章 事件的访问
2010/02/07 Javascript
一个简单的js树形菜单
2011/12/09 Javascript
有关于JS辅助函数inherit()的问题
2013/04/07 Javascript
Angularjs注入拦截器实现Loading效果
2015/12/28 Javascript
javascript实现数字倒计时特效
2016/03/30 Javascript
基于BootStrap Metronic开发框架经验小结【七】数据的导入、导出及附件的查看处理
2016/05/12 Javascript
简单谈谈axios中的get,post方法
2017/06/25 Javascript
微信小程序使用picker实现时间和日期选择框功能【附源码下载】
2017/12/11 Javascript
解决vue-cli + webpack 新建项目出错的问题
2018/03/20 Javascript
JavaScript生成指定范围随机数和随机序列的方法
2018/05/05 Javascript
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
[01:05]主宰至宝剑心之遗
2017/03/16 DOTA
[37:29]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.19
2020/11/19 DOTA
Python实现网站注册验证码生成类
2017/06/08 Python
Python运维开发之psutil库的使用详解
2018/10/18 Python
Python产生一个数值范围内的不重复的随机数的实现方法
2019/08/21 Python
python 利用jinja2模板生成html代码实例
2019/10/10 Python
Python中的None与 NULL(即空字符)的区别详解
2020/09/24 Python
浅谈Selenium+Webdriver 常用的元素定位方式
2021/01/13 Python
在python3.9下如何安装scrapy的方法
2021/02/03 Python
html5弹跳球示例代码
2013/07/23 HTML / CSS
Marlies Dekkers内衣美国官方网上商店:高端内衣品牌
2018/11/12 全球购物
墨尔本复古时尚品牌:Dangerfield
2018/12/12 全球购物
学校食堂食品安全承诺书
2015/04/29 职场文书
2015年试用期工作总结范文
2015/05/28 职场文书
同步小康驻村工作简报
2015/07/20 职场文书
企业反腐倡廉心得体会
2015/08/15 职场文书
《黄道婆》教学反思
2016/02/22 职场文书
Vue详细的入门笔记
2021/05/10 Vue.js
详解SpringBoot异常处理流程及原理
2021/06/21 Java/Android