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 相关文章推荐
为Java项目添加Redis缓存的方法
May 18 Redis
Redis性能监控的实现
Jul 09 Redis
厉害!这是Redis可视化工具最全的横向评测
Jul 15 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
源码分析Redis中 set 和 sorted set 的使用方法
Mar 22 Redis
浅谈Redis 中的过期删除策略和内存淘汰机制
Apr 03 Redis
解决 Redis 秒杀超卖场景的高并发
Apr 12 Redis
windows安装 redis 6.2.6最新步骤详解
Apr 26 Redis
Redis高并发缓存架构性能优化
May 15 Redis
Redis特殊数据类型Geospatial地理空间
Jun 01 Redis
Redis基本数据类型哈希Hash常用操作命令
Jun 01 Redis
Redis主从复制操作和配置详情
Sep 23 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 #Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
You might like
PHP备份/还原MySQL数据库的代码
2011/01/06 PHP
windows环境下php配置memcache的具体操作步骤
2013/06/09 PHP
一个完整的PHP类包含的七种语法说明
2015/06/04 PHP
在WordPress中安装使用视频播放器插件Hana Flv Player
2016/01/04 PHP
基于PHP生成简单的验证码
2016/06/01 PHP
PHP实现打包下载文件的方法示例
2017/10/07 PHP
基于jQuery的让非HTML5浏览器支持placeholder属性的代码
2011/05/24 Javascript
JavaScript地图拖动功能SpryMap的简单实现
2013/07/17 Javascript
基于jquery实现等比缩放图片
2014/12/03 Javascript
jQuery中andSelf()方法用法实例
2015/01/08 Javascript
jQuery及JS实现循环中暂停的方法
2015/02/02 Javascript
js闭包实现按秒计数
2015/04/23 Javascript
jquery实现Li滚动时滚动条自动添加样式的方法
2015/08/10 Javascript
js 判断各种数据类型的简单方法(推荐)
2016/08/29 Javascript
BootStrap Table 设置height表头与内容无法对齐的问题
2016/12/28 Javascript
微信小程序 增、删、改、查操作实例详解
2017/01/13 Javascript
了解VUE的render函数的使用
2017/06/08 Javascript
JS实现延迟隐藏功能的方法(类似QQ头像鼠标放上展示信息)
2017/12/28 Javascript
详解组件库的webpack构建速度优化
2018/06/18 Javascript
Vue-Router基础学习笔记(小结)
2018/10/15 Javascript
Angular中使用ng-zorro图标库部分图标不能正常显示问题
2019/04/22 Javascript
Python采用raw_input读取输入值的方法
2014/08/18 Python
详解python-图像处理(映射变换)
2019/03/22 Python
python 扩展print打印文件路径和当前时间信息的实例代码
2019/10/11 Python
python 无损批量压缩图片(支持保留图片信息)的示例
2020/09/22 Python
python 基于opencv 绘制图像轮廓
2020/12/11 Python
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
The North Face北面法国官网:美国著名户外品牌
2019/11/01 全球购物
地球鞋加拿大官网:Earth Shoes Canada
2020/11/17 全球购物
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
通用C#笔试题附答案
2016/11/26 面试题
个人思想理论学习的自我鉴定
2013/11/30 职场文书
学生会离职感言
2014/02/11 职场文书
2014年科研工作总结
2014/12/03 职场文书
小学班主任工作总结2015
2015/04/07 职场文书
2015年评职称工作总结范文
2015/04/20 职场文书