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实现秒杀功能的简单方法
May 08 Redis
基于Redis位图实现用户签到功能
May 08 Redis
Redis 配置文件重要属性的具体使用
May 20 Redis
在redisCluster中模糊获取key方式
Jul 09 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 Redis
redis中lua脚本使用教程
Nov 01 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
Redis如何使用乐观锁(CAS)保证数据一致性
Mar 25 Redis
一文搞懂Redis中String数据类型
Apr 03 Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 Redis
Redis Lua脚本实现ip限流示例
Jul 15 Redis
基于Redission的分布式锁实战
Aug 14 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 #Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
You might like
php下HTTP Response中的Chunked编码实现方法
2008/11/19 PHP
PHP无限分类代码,支持数组格式化、直接输出菜单两种方式
2011/05/18 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
如何重写Laravel异常处理类详解
2020/12/20 PHP
根据分辨率不同,调用不同的css文件
2006/08/25 Javascript
IE与firefox之jquery用法区别
2008/10/03 Javascript
jQuery滚动加载图片效果的实现
2013/03/06 Javascript
移动端 一个简单易懂的弹出框
2016/07/06 Javascript
EasyUI 中combotree 默认不能选择父节点的实现方法
2016/11/07 Javascript
jQuery命名空间与闭包用法示例
2017/01/12 Javascript
JS实现AES加密并与PHP互通的方法分析
2017/04/19 Javascript
详解React Native网络请求fetch简单封装
2017/08/10 Javascript
React Native实现地址挑选器功能
2017/10/24 Javascript
微信小程序异步处理详解
2017/11/10 Javascript
JavaScript数组,JSON对象实现动态添加、修改、删除功能示例
2018/05/26 Javascript
JS执行控制之节流模式实例分析
2018/12/21 Javascript
JS代码触发事件代码实例
2020/01/02 Javascript
Python版实现微信公众号扫码登陆
2020/05/28 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
2020/07/30 Javascript
[01:02:26]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第二场 1月18日
2021/03/11 DOTA
pycharm 使用心得(八)如何调用另一文件中的函数
2014/06/06 Python
在Python中使用poplib模块收取邮件的教程
2015/04/29 Python
在Python中处理字符串之ljust()方法的使用简介
2015/05/19 Python
Python正则抓取新闻标题和链接的方法示例
2017/04/24 Python
PyQt5每天必学之切换按钮
2020/08/20 Python
python获取本机所有IP地址的方法
2018/12/26 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
利用pipenv和pyenv管理多个相互独立的Python虚拟开发环境
2020/11/01 Python
jupyter 添加不同内核的操作
2021/02/06 Python
福克斯租车:Fox Rent A Car
2017/04/13 全球购物
德国在线购买葡萄酒网站:Geile Weine
2019/09/24 全球购物
写出程序把一个链表中的接点顺序倒排
2014/04/28 面试题
数控专业个人求职信范例
2013/11/29 职场文书
领导班子四风对照检查材料范文
2014/09/27 职场文书
《孙子兵法》:欲成大事者,需读懂这些致胜策略
2019/08/23 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python