Redis代替session,这个替代不是简单的说你将数据存入redis就行了,在业务流程上会有比较多的一些变化,这节就一起来分析一下基于redis代替session之后业务上有哪些变化。
一、发送短信验证码
先来看发送短信验证码,整体来讲这个流程没什么大的变化,但是在保存的时候,以前是保存在session,现在就是保存到redis中了。
![image-20240525085558035](https://img-blog.csdnimg.cn/img_convert/ed4fed1b03f9f282ea1b7851d30337e1.png)
但是这里有一个问题,redis是一个键值型的数据结构,但是它的value类型有很多种,那么到底使用哪种结构呢?
所以我们可以使用String结构,就是一个简单的key,value键值对的方式,但是关于key的处理,session他是每个用户都有自己的session,但是redis的key是共享的,如果每个session发生的请求存储的key都为code,就会覆盖,因此咱们就不能使用code了。
既然手机号是唯一的,如果我们采用phone不就好了吗?是这样的,用户在提交的时候刚好也是提交手机号和验证码,这也为我们的存储带来了方便。
二、登录
但是在登录的时候,保存进redis的是一个用户的对象,那value应该使用哪种数据类型来存储呢?
先来回顾一下两种常用的数据结构:如果存入的数据比较简单,我们可以考虑使用String。但如果一些复杂的数据类型,如String,那么可以考虑使用哈希。
如下图,如果使用String,同学们注意他的value,会额外占用一点空间,将Java对象序列化为JSON字符串然后进行保存。如果使用哈希,则他的value中只会存储他数据本身,占据的空间更小,并且针对单个字段做CRUD更加灵活。
如果不是特别在意内存,其实使用String就可以啦。但是如果我们从优化的角度考虑,其实推荐大家使用哈希这种方式。
在这个案例中,我们会选择哈希结构来保存用户信息。
![1653319261433](https://img-blog.csdnimg.cn/img_convert/c82d24a228ee64e6d22f10fbf9028c4b.png)
接下来就是考虑用什么key进行存储了,key的存储应该满足以下几个条件
1、key要具有唯一性
2、key要方便携带
手机号这个的数据来存储当然是可以的,但是如果把这样的敏感数据存储到redis中并且从页面中带过来毕竟不太合适,所以我们在后台生成一个随机串token(例如UUID),然后让前端带来这个token就能完成我们的整体逻辑了。
三、整体访问流程
当注册完成后,用户去登录会去校验用户提交的手机号和验证码,是否一致,如果一致,则根据手机号查询用户信息,不存在则新建,最后将用户数据保存到redis,并且生成token作为redis的key,当我们校验用户是否登录时,会去携带着token进行访问,从redis中取出token对应的value,判断是否存在这个数据,如果没有则拦截,如果存在则将其保存到threadLocal中,并且放行。
但是问题来了,这个token,tomcat并不会帮我们自动写到浏览器上,因此我们只能手动将token返回给客户端,然后客户端把这个信息保存下来,以后每次请求它都能携带这个token了,服务器看到它拿到的这个token后,就可以基于token从redis获取用户信息了。
四、扩展
前端每次请求都需要携带token到服务器,那它是怎么做到这一点的呢?我们一起来看一下前端的代码。
前端会将token保存到sessionStorage,sessionStorage是浏览器的一种存储方式。
![image-20240525091029507](https://img-blog.csdnimg.cn/img_convert/5c0a336245be52b880838db6eda511fd.png)
axios.interceptors.response.use
是axios的请求拦截器,它会在每次请求的时候都执行这段逻辑。
这里是将token放入到请求头中,这个请求头的名字叫 authorization
,这样就可以确保以后,凡是有axios发起的这种请求,也就是所有的AJAX请求,都会携带 authorization
头,将来在服务端就可以获取 authorization
请求头,从而拿到token,从而去实现对于登录功能的验证了。
![image-20240525091728797](https://img-blog.csdnimg.cn/img_convert/51876433f48a80c47a6a9bbc7797a790.png)
因此登录凭证其实是保存在前端浏览器的。