多平台登录APP修改密码后退出登录的Redis实现

有一款APP,可以多设备平台同时登录,但现在要求只要有一台设备用户密码修改后,所有平台必须强制退出,输入新的密码重新登录。出于用户账号安全考虑,这样的设计是必要且必须的,那么后台具体该如何实现呢?下面讲下我的思路及实现方法。

这个时候首先想到了用Redis,起初的想法很简单,在登录时以用户编号作为key, 随机一个uuidStr,String uuidStr=UUID.randomUUID().toString().replaceAll("-", “”);作为value,在登录时将此key-value 存入Redis,在接口拦截器里过滤掉登录接口,当调用为非登录接口时,用传过来的用户编号作为key去拿Redis里的value,如果拿到的value为空,则对外抛出异常,APP端收到异常状态后控制跳转到登录页。当修改密码时,会清掉Redis里所有key值为用户编号的键值对。这样当修改密码时,所有登录用户就会因为取不到Redis里的value而被跳转到登录页,从而解决问题。

但在实现上却出现了问题,首先,系统里其他业务里已经出现了以用户编号为key的Redis缓存,如果以用户编号清除,会不会影响其他业务?其次,还有个更严重的问题:假如有A和B两个设备登录了小明的账户,其中小明在A设备上修改了密码,此时Redis被清空,但小明又在A设备上重新登录,此时Redis中又存入了以小明用户编号为key的值,B设备去访问其他功能的接口,由于不同设备key没有区分,都是小明的用户编号,所以到了过滤器里仍然能通过Redis校验,去访问其他接口服务,而不会被退出登录。

为了解决这两个问题,我首先把key的生成规则做了改变,原来key=userNbr,现在加上表示渠道的字符串,后面再加上随机生成的uuidStr,比如这个用于修改密码场景,key=“change_pwd_”+userNbr+"_login_"+uuidStr。这样就不会与其他业务的Redis的key值弄混,
同时引入token,即在登录之后会返回一个唯一的loginToken,这个loginToken的值即为Redis的key,代码片段如下:

            String uuidStr=UUID.randomUUID().toString().replaceAll("-", "");
            String loginToken="change_pwd_"+user.getNbr()+"_login_"+uuidStr;
            redisService.addToRedisString(loginToken, uuidStr);
            resModel.setLoginToken(loginToken);

用户每次请求其他接口都会把这个loginToken作为参数传过来。我在接口拦截器里会做校验。代码片段如下:

        /**获得解密报文交易编号*/
		String transcode = securityModel.getTransCode();
		 /**交易编号不为登录交易时*/
        if (StringUtil.isNotEmpty(transcode) && !StringUtil.equals("sysLogin", transcode) ) {
            String loginTokenValue = null;
             /**loginToken不为空时,去Redis取value值*/
            if (!StringUtil.isEmpty(baseReqModel.getLoginToken())) {
                loginTokenValue = redisService.getToStringByKey(baseReqModel.getLoginToken());
            }
			/**loginToken为空或者value为空时,向前端抛异常*/
            if (StringUtil.isEmpty(baseReqModel.getLoginToken())
                || StringUtil.isEmpty(loginTokenValue)) {

                log.error("============loginToken超时,请检查!============");
                PrintWriter out = response.getWriter();
                // 组装报错响应报文
                BaseResModel resModel = new BaseResModel();
                resModel.setResCode(BusinessBaseCode.RETURN_LOGIN_TOEKN_EXPIRED.getCode());
                resModel.setResMsg(BusinessBaseCode.RETURN_LOGIN_TOEKN_EXPIRED.getDesc());
                resModel.setResponseTime(new Date());
                String respMsg = MobileMessageUtil.packageMsg(resModel);
                String respHash = MobileMessageUtil.getMsgHash(respMsg);
                String resp = MobileMessageUtil.packageResp(respMsg, respHash);
                out.print(resp);
                out.flush();
                out.close();
                return false;
            }
        }

这样也确保每台设备登录产生的Key值是唯一的,每台设备的请求因为引入了loginToken,所以也是不同的,此时只要在修改密码时,清除Redis里以"change_pwd_"+user.getNbr()+"_login_"开头的所有key即可。代码片段如下:

			String loginKey="change_pwd_"+user.getNbr()+"_login_";		
			redisService.deleteSimilarStringByKey(loginKey);

这样小明在A设备修改密码后重新登录,B设备在拦截器中的value值是null,会抛出异常,APP会强制跳转到登录页。预期功能实现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值