Redis实战(一)

我学习了黑马程序员的redis课程,做点笔记供大家和我自己参考。下图所有的redis实战系列都是基于的黑马点评项目。

一、短信登录

1.导入黑马点评项目

本项目没有微服务架构,是一个前后端分离的单体式项目,前端部署在nignx上,后端项目在idea中打开即可,虽然是单体项目但是我们需要考虑它的水平扩展能力,即项目部署在tomcat上后,单台tomcat扛不住压力,能够形成一个集群,在多台tomcat上部署项目。

项目文件大家可以通过下列网盘链接进行下载

链接:https://pan.baidu.com/s/18GcAvgwhn8VoJtI8B7_6Nw?pwd=0pfe 
提取码:0pfe

导入sql文件简单就不赘述了。

(1)导入后端项目

修改mysql和redis信息

运行,在浏览器中输入localhost:8081/shop-type/list,看看是否成功。

(2)导入前端项目

前端已经部署在nignx上面,所以导入比较简单,只需在cmd窗口输入start nginx.exe。

在浏览器中打开看看是否成功:输入黑马点评

到这项目就导入完毕了。

2.基于Session实现短信登录

实现短信登录流程为:发送短信验证码短信验证码登录、注册,登录后请求需要校验登录状态

 (1)发送短信验证码

根据前端发送验证码的请求,找到对应的接口类UserController

 IUserInfoService类,补充这个方法

 

根据上图流程,在  IUserInfoServiceImp类中写出下图代码

在网页中输入手机号码,点击发送验证码,可以在idea的控制台中看到验证码

(2)短信验证码登录、注册

根据前端登录的请求,找到对应的接口类UserController

 IUserService类,补充这个方法

 根据上图流程,在  IUserInfoServiceImp类中写出下图代码

然后在浏览器中尝试登陆,验证一下是否成功。 

我们可以发现登录后,跳转到首页,但是如果点击到我的页面就会跳到登录界面(未授权),这就需要校验登录了。

(3)校验登录状态

随着业务的完善,除了 UserController类中的login需要校验登录,还会有OrderController等其他Controller类需要校验登录,我们可以使用springmvc中的拦截器,就不用在Controller类中补充校验登录了。然而,这些Controller类可能需要用户信息,我们需要将拦截器中拦截得到的信息传递到Controller类中,在传递过程中需要注意多线程并发修改的安全问题。这个问题可用ThreadLocal(线程序对象)解决。每一个进入tomcat的请求都是一个独立的线程,ThreadLocal为每一个线程开辟一个独立的空间用来保存用户信息,这样每个线程互不干扰。用户访问不同的Controller或不同用户访问同一Controller,都有自己的用户信息。

①编写拦截器

再utils文件下创建一个loginInterceptor类,编写上图流程的代码

②配置拦截器

编写config类MvcConfig

 ③在对应的controller类UserController中编写放行后的代码

(4)隐藏用户敏感信息

我们可以发现,返回的用户信息太多了,而且这些信息保存在session中,会加大session的压力。

 应该只保留重要的数据,我们使用已定义好的UserDTO实体类替换原来的User类。

重新登陆验证一下是否成功。

3.基于Redis实现共享session登录

(1)session共享的问题

多台tomcat并不共享session存储空间,当请求切换到不同tomcat服务时导致数据丢失的问题。

在实际情况中,为了应对并发,需要水平扩展,部署多台tomcat形成负载均衡的集群。当nginx接收的请求时,它会进行负载均衡,对所有tomcat轮询,选择一台tomcat。每个tomcat都有自己的session空间,用户信息被保存在被选择的这台tomcat中,但是当nginx接收到另一个请求时,它可能会选择另一台tomcat,这台tomcat没有保存用户信息,会认为用户当前没有登录。

tomcat之前考虑过通过拷贝让session共享:tomcat通过配置让他们之间互相可以实现一个数据拷贝。然而,多台tomcat保存相同的数据,会造成内存浪费,而且拷贝会有一定的延迟,延迟之内访问可能会导致数据不一致。

有什么东西可以满足数据共享内存存储key、value结构这三个条件?

redis是tomcat之外的,每个tomcat都能访问redis,便可实现数据共享;session是基于内存的,读写效率高,读写性能比较差的话难以满足高并发的需求,redis也是内存存储;redis也是key、value结构的。所以,可以用redis代替session。

(2)redis代替session

使用redis代替session,保存数据需考虑好key和value。

①验证码要保存在redis中

验证码只有6个数字,所以value可以用string类型。

key要考虑唯一性和用户可以携带这个key来读取数据。不能像session使用code作为key,因为浏览器发送请求时都有一个独立的session(在tomcat中维护了很多的session),而redis是一个共享的空间,使用code会被其他请求的验证码覆盖,考虑到唯一性,我们可以使用电话号码作为key。同时,后面获取验证码时,使用session不用考虑取数据的问题,因为浏览器第一次请求,tomcat会给浏览器创建一个session,生成sessionID,写到用户浏览器的cookie中,之后每次请求都会带着cookie,带着sessionID,也就找到session,从session中取数据。而redis通过用户提交的手机号获取验证码。

② 用户要保存在redis中。

 value的数据类型可以使用string,也可以使用哈希,这里我们使用hash,因为hash修改比较方便。

key这里不推荐使用phone,推荐使用随机token。登录校验时,基于session是通过cookie(请求时携带)中的session ID获得用户数据。我们使用随机token作为key,在保存完用户信息后,返回token给客户端,前端之后每次请求都携带这个token(前端具体操作看下图)

 

由此可知登录凭证token保存在前端浏览器中,如果用phone就会有泄露风险。

 (2)redis代替session实现

①redis保存验证码

保存常量

②redis保存用户信息

 保存常量

token的有效期不能是生成的30分钟后过期,应该是有30分钟没有访问后过期,而这个访问可以通过登录校验来更新。

③修改loginInterceptor函数

(3)优化拦截器

我们知道目前的拦截器拦截的是需要登录校验的请求,在访问不会拦截的页面时,会导致token的有效期不会被更新,所以我们需要优化一下。

我们可以再创建一个拦截器,负责获取token、保存、刷新oken有效期等,这是对所有请求都执行的拦截,而另一个拦截器拦截需要登录校验的请求。

在utils文件下再创建一个 RefreshTokenInterceptor类。

原本的loginInterceptor类也需要修改

然后就是配置拦截器了

  • 29
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值