一篇文章带你走进cookie,session,Token的世界

前言

无状态的HTTP协议

一天,你有个需求,你要去超市买一瓶可乐。 到了超市买了可乐,你告诉售货员,下次给我准备下雷碧,我下次来拿。 第二次,你去超市拿雷碧,售货员说他不记得你什么时候说要准备雷碧。 这次你学聪明了,售货员给你写了个纸条,上面有超市的章印,下次你带着纸条来,买上了超市 给你准备的雷碧

  1. http超文本传输协议:Hyper Text Transfer Protocol
  2. http不会为了下次连接所需要的信息而维护这次连接
  3. 就像你去超市买可乐,买完就结束了,它不会记录你告诉他的信息,不会记录你下次还要买雷碧,下次他也不知道你曾经来过
  4. 顾名思义无状态是指,当浏览器发送请求给server的时候,server响应,可是同一个浏览器再发送请求给server的时候,他会响应,可是他不知道你就是刚才那个浏览器,简单地说,就是server不会去记得你,所以是无状态协议。而DNS是有状态协议
  5. 再举个例子,像购物车,你买东西加入购物车,如果http协议的话,刷新页面,购物车就为空了。

一、cookie

一篇文章带你走进cookie,session,Token的世界

cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据。跟服务器没啥关系,仅仅是浏览器实现的一种数据存储功能。

cookie由服务器生成,发送给浏览器,浏览器把cookie以KV形式存储到某个目录下的文本文件中,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间。所以每个域的cookie数量是有限制的。

如何设置

客户端设置

document.cookie = "name=xiaoming; age=12 "

设置cookie => cookie被自动添加到request header中 => 服务端接收到cookie


服务端设置

不管你是请求一个资源文件(如html/js/css/图片), 还是发送一个ajax请求, 服务端都会返回response.而response header中有一项叫set-cookie, 是服务端专门用来设置cookie的;

Cookie,SessionStorage,LocalStorage

HTML5提供了两种本地存储的方式 sessionStorage 和 localStorage;

一篇文章带你走进cookie,session,Token的世界

二、Session

Cookie是存储在客户端方,Session是存储在服务端方,客户端只存储SessionId


在上面我们了解了什么是Cookie,既然浏览器已经通过Cookie实现了有状态这一需求,那么为什么又来了一个Session呢?这里我们想象一下,如果将账户的一些信息都存入Cookie中的话,一旦信息被拦截,那么我们所有的账户信息都会丢失掉。所以就出现了Session,在一次会话中将重要信息保存在Session中,浏览器只记录SessionId一个SessionId对应一次会话请求。

 1@RequestMapping("/testSession")
 2@ResponseBody
 3public String testSession(HttpSession session){
 4    session.setAttribute("testSession","this is my session");
 5    return "testSession";
 6}
 7
 8
 9@RequestMapping("/testGetSession")
10@ResponseBody
11public String testGetSession(HttpSession session){
12    Object testSession = session.getAttribute("testSession");
13    return String.valueOf(testSession);
14}

这里我们写一个新的方法来测试Session是如何产生的,我们在请求参数中加上HttpSession session,然后再浏览器中输入http://localhost:8005/testSession进行访问可以看到在服务器的返回头中在Cookie中生成了一个SessionId。然后浏览器记住此SessionId下次访问时可以带着此Id,然后就能根据此Id找到存储在服务端的信息了。

一篇文章带你走进cookie,session,Token的世界

此时我们访问路径http://localhost:8005/testGetSession,发现得到了我们上面存储在Session中的信息。那么Session什么时候过期呢?

一篇文章带你走进cookie,session,Token的世界

既然我们知道了Session是在服务端进行管理的,那么或许你们看到这有几个疑问,Session是在在哪创建的?Session是存储在什么数据结构中?接下来带领大家一起看一下Session是如何被管理的。

Session的管理是在容器中被管理的,什么是容器呢?Tomcat、Jetty等都是容器。接下来我们拿最常用的Tomcat为例来看下Tomcat是如何管理Session的。在ManageBase的createSession是用来创建Session的。

 1@Override
 2public Session createSession(String sessionId) {
 3    //首先判断Session数量是不是到了最大值,最大Session数可以通过参数设置
 4    if ((maxActiveSessions >= 0) &&
 5            (getActiveSessions() >= maxActiveSessions)) {
 6        rejectedSessions++;
 7        throw new TooManyActiveSessionsException(
 8                sm.getString("managerBase.createSession.ise"),
 9                maxActiveSessions);
10    }
11
12    // 重用或者创建一个新的Session对象,请注意在Tomcat中就是StandardSession
13    // 它是HttpSession的具体实现类,而HttpSession是Servlet规范中定义的接口
14    Session session = createEmptySession();
15
16
17    // 初始化新Session的值
18    session.setNew(true);
19    session.setValid(true);
20    session.setCreationTime(System.currentTimeMillis());
21    // 设置Session过期时间是30分钟
22    session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);
23    String id = sessionId;
24    if (id == null) {
25        id = generateSessionId();
26    }
27    session.setId(id);// 这里会将Session添加到ConcurrentHashMap中
28    sessionCounter++;
29
30    //将创建时间添加到LinkedList中,并且把最先添加的时间移除
31    //主要还是方便清理过期Session
32    SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
33    synchronized (sessionCreationTiming) {
34        sessionCreationTiming.add(timing);
35        sessionCreationTiming.poll();
36    }
37    return session
38}

到此我们明白了Session是如何创建出来的,创建出来后Session会被保存到一个ConcurrentHashMap中。可以看StandardSession类。

1protected Map sessions = new ConcurrentHashMap<>();

到这里大家应该对Session有简单的了解了。

Session是存储在Tomcat的容器中,所以如果后端机器是多台的话,因此多个机器间是无法共享Session的,此时可以使用Spring提供的分布式Session的解决方案,是将Session放在了Redis中。


三、Token

1、什么的Token

Token是首次登陆时由服务器下发,作为客户端进行请求的一个令牌,当交互时用于身份验证的一种验证机制,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

2、Token的作用

3、Token身份认证的过程

4、Token的存储位置

优点:没有时间限制的存储,会一直存放在浏览器中。

缺点:由于LocalStorage 可以被 javascript 访问,所以容易受到XSS攻击。所以可以在一个统一的地方复写请求头,让每次请求都在header中带上这个token, 当token失效的时候,后端会返回401,这个时候在你可以在前端代码中操作返回登陆页面,清除localstorage中的token。(适用于 ajax请求或者 api请求,可以方便的存入 localstorage)另外,需要应用程序来保证Token只在HTTPS下传输。

优点:可以防止 csrf攻击,因为 csrf只能在请求中携带 cookie,而这里必须从 cookie中拿出相应的值并放到 authorization 头中。实际上cookie不能跨站(同源策略)被取出,因此可以避免 csrf 攻击。(适用于 ajax请求或者 api请求,可以方便的设置 auth头)

5、Token处理过期时间

在我的vue项目中,我将Token存储在了localStorage中,有处理过Token过期,我是这样做的:

created() {
    if (localStorage.jwtToken) {
      const decoded = jwt_decode(localStorage.jwtToken);
      //获取当前时间
      const currentTime = Date.now() / 1000;
      //检测token是否过期
      if (decoded.exp < currentTime) {
        //跳转到登录页面
        this.$router.push('/login');
        //其他处理
        ...
      } else{
        //没有过期的处理;
      }   
    }

四、总结

cookie,session,Token没有绝对的好与坏之分,只要还是要结合实际的业务场景和需求来决定采用哪种方式来管理回话,当然也可以三种都用。

展开阅读全文

页面更新:2024-04-13

标签:服务端   客户端   下次   浏览器   状态   协议   超市   服务器   时间   世界   信息

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top