一.有哪些go session相关库?
github.com/gin-contrib/sessions
github.com/gorilla/sessions
二.阅读源码
先上一张这些库里的数据结构的关联图,如下:
为了方便文章后面的叙述,这里把github.com/gin-contrib/sessions库下的sessions数据结构叫sessions1,github.com/gorilla/sessions库下的sessions数据结构叫sessions2。
如果想保护服务器的资源,必须限制浏览器的请求;要限制浏览器的请求,必须鉴别浏览器的请求。由于http是无状态的协议,所以采用会话机制(cookie+session)维护浏览器和服务器的一个状态。cookie是浏览器存储少量数据的一种机制,以key、value的形式存储数据。
github.com/gin-contrib/sessions库是作为gin框架的中间件使用的,这里就是为什么sessions1要再封装一层sessions2,并且github.com/gin-contrib/sessions库支持了很多store(store是什么呢?store就是用来存储会话的,store可以是cookie、redis、mongo等)。所以会话机制的主要实现主要看github.com/gorilla/sessions这个库。
那github.com/gorilla/sessions库是怎么实现这个会话机制的呢?
1.创建会话
我们看到sessions2下有个store,这个store就是sessions1下的store。可以通过设置sessions1下的store来确定我们用什么存储会话。这里我用的store是redis。
通过阅读github.com/gorilla/sessions的源码我们可以知道,会话的内容就是sessions2数据结构里面包含的数据。redisStore创建了sessions2,并把sessions2.keyPrefix+sessions2.ID作为redis的key存储sessions2。然后设置cookie,cookie的key值是sessions2的name(sessions2的name与sessions1的name是一样的),cookie的value就是加密过的sessions2的ID。
2.获取会话
会话既然是存储在redisStore里,那获取也当然是从redisStore里获取呢。
通过源码可知获取seesion其实就是通过获取到cookie中key为sessions2.name的值(这个值就是sessions2.ID),,然后再通过把sessions2.keyPrefix+sessions2.ID当作redis的key,获取存在这个redis key的值(这就值就是会话内容)。