广告
返回顶部
首页 > 资讯 > 精选 >Redis如何实现登录注册
  • 277
分享到

Redis如何实现登录注册

2023-07-02 08:07:43 277人浏览 泡泡鱼
摘要

今天小编给大家分享一下Redis如何实现登录注册的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 引言在传统的项目中,用户

今天小编给大家分享一下Redis如何实现登录注册的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

1. 引言

在传统的项目中,用户登录成功,将用户信息保存在session中,这种方式在微服务架构中会产生一系列问题。例如在购物车服务具有多台服务器,当一个请求落在购物车1号服务器后,其session保存了用户信息,另一个请求落在了购物车2号服务器,发现没有用户信息,则重新需要进行登录。服务器之间有session不共享的问题。为了解决这一问题,Tomcat提出了内存拷贝,即只需要配置一些信息即可实现多台服务器之间的session拷贝,但是这种解决方案也有缺陷,例如:

  • 浪费空间

  • 拷贝有延时,如果在延时内有请求访问,则还会出现上述问题

为了解决此类问题,我们需要使用多个服务共享的信息平台,例如Redis

2. 流程图及代码实现

直接上流程图

Redis如何实现登录注册

流程图简洁明了,其中需要注意的是

Redis中存入验证码的key是手机号拼接的字符串,为什么保存用户到Redis的key要使用随机token,而不是手机号拼接的字符串呢?

因为在用户登录注册时,服务器会获取到手机号,所以可以使用手机号作为key,进行验证手机号和验证码时也方便进行匹对,那么在保存用户信息到Redis时为什么要使用随机token呢?因为在用户独立成功后,用户的每次请求都会携带cookie,如果将保存用户信息的key设置为含手机号的,那么用户的请求中的cookie也需要携带手机号,这样就会有一定的安全风险,所以在用户登录成功后,我们随机生成token,用token作为key,并且返回给前端token,这样前端请求时就会携带token,也避免了安全隐患。

2.1 生成验证码保存到Redis

   @Override    public Result sedCode(String phone, httpsession session) {        //1. 校验手机号        if (RegexUtils.isPhoneInvalid(phone)) {            //2.如果不符合,返回错误信息            return Result.fail("手机号格式错误");        }        // 3.从redis里获取验证码是否存在        if(null==stringRedisTemplate.opsForValue().get("loginCode" + phone)){            log.info("请勿重复获取验证码");            return Result.fail("请勿重复获取验证码");        }        //4. 符合,生成验证码        String code = RandomUtil.randomNumbers(6);        //5. 保存验证码到redis,并设置有效期1分钟,在设置key的时候,可以提前设置一个常量,然后在这里引用即可        stringRedisTemplate.opsForValue().set("loginCode:"+phone,code,1, TimeUnit.MINUTES);        //5. 发送验证码 模拟发送        log.debug("发送短信验证码成功,验证码:{}",code);        //返回ok        return Result.ok();    }

2.2 登录验证

@Override    public Result login(LoginFORMDTO loginForm, HttpSession session) {        //1. 校验手机号        String phone = loginForm.getPhone();        if (RegexUtils.isPhoneInvalid(phone)) {            return Result.fail("手机号格式错误");        }        //2. 获取Redis中的校验验证码        String cacheCode = stringRedisTemplate.opsForValue().get("loginCode" + phone);        // 3.获取表单中的验证码        String code = loginForm.getCode();        if (cacheCode == null || !cacheCode.toString().equals(code)){            //3. 不一致,报错            return Result.fail("验证码错误");        }        //4.一致,根据手机号查询用户        User user = query().eq("phone", phone).one();        //5. 判断用户是否存在        if (user == null){            //6. 不存在,创建新用户            user = createUserWithPhone(phone);        }        //7.保存用户信息到session        // 生成token        String token = UUID.randomUUID().toString();        // 将User转为Map        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);        Map<String, Object> userDtoMap = BeanUtil.beanToMap(userDTO);        // 存储        stringRedisTemplate.opsForHash().putAll("login:token:"+token,userDtoMap);        // 设置有效期30分钟        stringRedisTemplate.expire("login:token:"+token,30, TimeUnit.MINUTES);        // 返回token给前端        return Result.ok(token);    }

2.3 请求拦截器

有些请求是需要用户登录才能进行访问的,所以我们设置一个登录拦截器先拦截请求,判断用户是否登录,如果登录了就进行放行即可。

Redis如何实现登录注册

1 实现HandlerInterceptor类

public class RefreshTokenInterceptor implements HandlerInterceptor {    private StringRedisTemplate stringRedisTemplate;    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {        this.stringRedisTemplate = stringRedisTemplate;    }    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        // 1.获取请求头中的token        String token = request.getHeader("authorization");        if (StrUtil.isBlank(token)) {            return true;        }        // 2.基于TOKEN获取redis中的用户        String key  = "login:token:" + token;        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);        // 3.判断用户是否存在        if (userMap.isEmpty()) {            return true;        }        // 5.将查询到的hash数据转为UserDTO        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);        // 6.存在,保存用户信息到 ThreadLocal        UserHolder.saveUser(userDTO);        // 7.刷新token有效期        stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);        // 8.放行        return true;    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        // 移除用户        UserHolder.removeUser();    }}

preHandle方法是在controller之前运行,在这个方法里面可以进行验证登录状态的操作。

  • 为什么要将用户保存到ThreadLocal?因为每一个线程都是独立的,如果将用户信息保存到公共变量中,会造成线程安全问题,每一个线程都具备一个ThreadLocal内存,我们将用户信息保存到ThreadLocal中即可实现线程独享一份用户信息

  • 为什么要刷新Redis中用户信息的有效时长?因为在session中,其机制是当用户不在使用session中的数据超过30分钟就会剔除session的数据,所以在拦截器的前置拦截中进行刷新即可

  • 上述代码的第三步骤,为什么userMap为空了还要放行呢?因为这个拦截器只是做Redis用户信息刷新存活时间的功能,真正拦截的是LoginInterceptor,LoginInterceptor代码在下面展示

public class LoginInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        // ThreadLocal中获取用户信息        if (UserHolder.getUser()==null){            response.setStatus(401);            return false;        }        // 放行        return true;    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        //移除用户        UserHolder.removeUser();    }}

两个拦截器配置了,但是没有生效,需要在配置类里进行配置

@Configurationpublic class mvcConfig implements WEBMvcConfigurer {    @Autowired    private StringRedisTemplate redisTemplate;    @Override    public void addInterceptors(InterceptorReGIStry registry) {        // 登录拦截器        registry.addInterceptor(new LoginInterceptor())                .excludePathPatterns(                        // 配置不需要被拦截的路径                        "/shop/**",                        "/voucher/**",                        "/shop-type/**",                        "/upload/**",                        "/blog/hot",                        "/user/code",                        "/user/login"                ).order(1);        registry.addInterceptor(new RefreshTokenInterceptor(redisTemplate))                .excludePathPatterns(                        "/user/login",                        "/user/code"                ).order(0);    }}

这里配置两个拦截器,两个拦截器是有先后顺序的,上述已经说明,通过设置order属性即可配置先后顺序,值越小,优先级越高。

以上就是“Redis如何实现登录注册”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

--结束END--

本文标题: Redis如何实现登录注册

本文链接: https://www.lsjlt.com/news/340528.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis如何实现登录注册
    今天小编给大家分享一下Redis如何实现登录注册的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 引言在传统的项目中,用户...
    99+
    2023-07-02
  • Redis实现登录注册的示例代码
    目录1. 引言2. 流程图及代码实现2.1 生成验证码保存到Redis2.2 登录验证2.3 请求拦截器3. 总结1. 引言 在传统的项目中,用户登录成功,将用户信息保存在sessi...
    99+
    2022-11-13
  • redis应用之——注册、登录
    字段设计:#设置登录帐号:set user:1:account zhangsanset user:2:account lisi#设置用户名:set user:1:name 张三set user:2:name...
    99+
    2022-10-18
  • JavaScript如何实现web登录注册
    今天小编给大家分享一下JavaScript如何实现web登录注册的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、前端基础准...
    99+
    2023-07-06
  • react如何实现登录和注册
    这篇文章主要介绍了react如何实现登录和注册的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇react如何实现登录和注册文章都会有所收获,下面我们一起来看看吧。react实现登录和注册的方法:1、搭建样式组件;...
    99+
    2023-07-04
  • springboot+VUE如何实现登录注册
    这篇文章主要介绍springboot+VUE如何实现登录注册,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、springBoot创建springBoot项目分为三个包,分别为controller,service, ...
    99+
    2023-06-15
  • 登录-注册网页实现
    re.php(登录的前端界面) 登录页面 .home{ text-align: center; font-wei...
    99+
    2023-08-31
    数据库 php 前端
  • springboot+VUE实现登录注册
    本文实例为大家分享了springboot+VUE实现登录注册的具体代码,供大家参考,具体内容如下 一、springBoot 创建springBoot项目 分为三个包,分别为contr...
    99+
    2022-11-12
  • android登录注册功能如何实现
    要实现Android的登录注册功能,你可以按照以下步骤进行操作:1. 创建一个布局文件来设计登录和注册界面。可以使用EditText...
    99+
    2023-10-20
    android
  • vue2.0+koa2+mongodb如何实现注册登录
    这篇文章将为大家详细讲解有关vue2.0+koa2+mongodb如何实现注册登录,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言前段时间和公司一个由技术转产品的同事探...
    99+
    2022-10-19
  • java如何实现注册登录系统
    本篇内容介绍了“java如何实现注册登录系统”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、创建菜单,注册,登录,退出2、注册模块:a) ...
    99+
    2023-06-30
  • QT如何实现用户登录注册
    本篇内容主要讲解“QT如何实现用户登录注册”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“QT如何实现用户登录注册”吧!具体代码如下#include "widget.h&quo...
    99+
    2023-07-02
  • Python如何实现注册登录功能
    这篇文章给大家分享的是有关Python如何实现注册登录功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体内容如下本文是用Python写一个注册登录功能,难度不大,很适合练手主要就是用列表和字典,以及逻辑判断用...
    99+
    2023-06-29
  • java如何实现登录注册界面
    这篇文章主要介绍“java如何实现登录注册界面”,在日常操作中,相信很多人在java如何实现登录注册界面问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java如何实现登录注册界面”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-02
  • java注册登录功能如何实现
    Java注册登录功能可以通过以下步骤来实现:1. 创建数据库表:- 创建一个用户表,包括用户ID(主键),用户名,密码等字段。2. ...
    99+
    2023-08-11
    java
  • java实现注册登录系统
    本文实例为大家分享了java实现注册登录系统的具体代码,供大家参考,具体内容如下 1、创建菜单,注册,登录,退出 2、注册模块: a) 通过键盘输入用户名,密码b) 保存用户名密码到...
    99+
    2022-11-13
  • node.js实现登录注册页面
    本文实例为大家分享了node.js登录注册页面展示的具体代码,供大家参考,具体内容如下 首先需要新建四个文件 一个服务器js 一个保存数据的txt 一个登陆、一个注册页面html 1、注册页面 <...
    99+
    2022-06-04
    页面 node js
  • Python实现注册登录功能
    用Python写个注册登录功能,供大家参考,具体内容如下 本文是用Python写一个注册登录功能,难度不大,很适合练手主要就是用列表和字典,以及逻辑判断用到的第3方库模块是time模...
    99+
    2022-11-13
  • Python实现用户登录注册
    简单的Python代码:用户登录注册 利用业余时间,写了一个用户进行登录注册的代码,非常简单。主要实现的功能是: 1、可以进行用户登录,在用户进行登录之前,对用户名进行检查,查看是否...
    99+
    2022-11-13
  • android实现注册登录程序
    本文实例为大家分享了android实现注册登录程序的具体代码,供大家参考,具体内容如下 注册页面: user_register.xml: <xml version="1.0" ...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作