前言

在了解这三个概念之前我们先要了解HTTP是无状态的Web服务器,什么是无状态呢?就像上面夏洛特烦恼中经典的一幕对话一样,一次对话完成后下一次对话完全不知道上一次对话发生了什么。如果在Web服务器中只是用来管理静态文件还好说,对方是谁并不重要,把文件从磁盘中读取出来发出去即可。但是随着网络的不断发展,比如电商中的购物车只有记住了用户的身份才能够执行接下来的一系列动作。所以此时就需要我们无状态的服务器记住一些事情。

那么Web服务器是如何记住一些事情呢?既然Web服务器记不住东西,那么我们就在外部想办法记住,相当于服务器给每个客户端都贴上了一个小纸条。上面记录了服务器给我们返回的一些信息。然后服务器看到这张小纸条就知道我们是谁了。那么Cookie是谁产生的呢?Cookies是由服务器产生的。接下来我们描述一下Cookie产生的过程。

  1. 浏览器第一次访问服务端时,服务器此时肯定不知道他的身份,所以创建一个独特的身份标识数据,格式为key=value,放入到Set-Cookie字段里,随着响应报文发给浏览器。
  2. 浏览器看到有Set-Cookie字段以后就知道这是服务器给的身份标识,于是就保存起来,下次请求时会自动将此key=value值放入到Cookie字段中发给服务端。
  3. 服务端收到请求报文后,发现Cookie字段中有值,就能根据此值识别用户的身份然后提供个性化的服务。

接下来我们用代码演示一下服务器是如何生成,我们自己搭建一个后台服务器,这里我用的是SpringBoot搭建的,并且写入SpringMVC的代码如下。

@RequestMapping("/testCookies")
public String cookies(HttpServletResponse response){response.addCookie(new Cookie("testUser","xxxx"));return "cookies";
}

项目启动以后我们输入路径http://localhost:8005/testCookies,然后查看发的请求。可以看到下面那张图使我们首次访问服务器时发送的请求,可以看到服务器返回的响应中有Set-Cookie字段。而里面的key=value值正是我们服务器中设置的值。

接下来我们再次刷新这个页面可以看到在请求体中已经设置了Cookie字段,并且将我们的值也带过去了。这样服务器就能够根据Cookie中的值记住我们的信息了。

接下来我们换一个请求呢?是不是Cookie也会带过去呢?接下来我们输入路径http://localhost:8005请求。我们可以看到Cookie字段还是被带过去了。

那么浏览器的Cookie是存放在哪呢?如果是使用的是Chrome浏览器的话,那么可以按照下面步骤。

  1. 在计算机打开Chrome
  2. 在右上角,一次点击更多图标->设置
  3. 在底部,点击高级
  4. 在隐私设置和安全性下方,点击网站设置
  5. 依次点击Cookie->查看所有Cookie和网站数据

然后可以根据域名进行搜索所管理的Cookie数据。所以是浏览器替你管理了Cookie的数据,如果此时你换成了Firefox等其他的浏览器,因为Cookie刚才是存储在Chrome里面的,所以服务器又蒙圈了,不知道你是谁,就会给Firefox再次贴上小纸条。

Cookie中的参数设置

说到这里,应该知道了Cookie就是服务器委托浏览器存储在客户端里的一些数据,而这些数据通常都会记录用户的关键识别信息。所以Cookie需要用一些其他的手段用来保护,防止外泄或者窃取,这些手段就是Cookie的属性。

参数名作用后端设置方法Max-Age设置cookie的过期时间,单位为秒cookie.setMaxAge(10)Domain指定了Cookie所属的域名cookie.setDomain("")Path指定了Cookie所属的路径cookie.setPath("");HttpOnly告诉浏览器此Cookie只能靠浏览器Http协议传输,禁止其他方式访问cookie.setHttpOnly(true)Secure告诉浏览器此Cookie只能在Https安全协议中传输,如果是Http则禁止传输cookie.setSecure(true)

下面我就简单演示一下这几个参数的用法及现象。

Path

设置为cookie.setPath("/testCookies"),接下来我们访问http://localhost:8005/testCookies,我们可以看到在左边和我们指定的路径是一样的,所以Cookie才在请求头中出现,接下来我们访问http://localhost:8005,我们发现没有Cookie字段了,这就是Path控制的路径。

Domain

设置为cookie.setDomain("localhost"),接下来我们访问http://localhost:8005/testCookies我们发现下图中左边的是有Cookie的字段的,但是我们访问http://172.16.42.81:8005/testCookies,看下图的右边可以看到没有Cookie的字段了。这就是Domain控制的域名发送Cookie。

接下来的几个参数就不一一演示了,相信到这里大家应该对Cookie有一些了解了。

Session

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

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

@RequestMapping("/testSession")
@ResponseBody
public String testSession(HttpSession session){session.setAttribute("testSession","this is my session");return "testSession";
}@RequestMapping("/testGetSession")
@ResponseBody
public String testGetSession(HttpSession session){Object testSession = session.getAttribute("testSession");return String.valueOf(testSession);
}

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

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

  • 客户端:和Cookie过期一致,如果没设置,默认是关了浏览器就没了,即再打开浏览器的时候初次请求头中是没有SessionId了。
  • 服务端:服务端的过期是真的过期,即服务器端的Session存储的数据结构多久不可用了,默认是30分钟。

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

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

@Override
public Session createSession(String sessionId) {//首先判断Session数量是不是到了最大值,最大Session数可以通过参数设置if ((maxActiveSessions >= 0) &&(getActiveSessions() >= maxActiveSessions)) {rejectedSessions++;throw new TooManyActiveSessionsException(sm.getString("managerBase.createSession.ise"),maxActiveSessions);}// 重用或者创建一个新的Session对象,请注意在Tomcat中就是StandardSession// 它是HttpSession的具体实现类,而HttpSession是Servlet规范中定义的接口Session session = createEmptySession();// 初始化新Session的值session.setNew(true);session.setValid(true);session.setCreationTime(System.currentTimeMillis());// 设置Session过期时间是30分钟session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);String id = sessionId;if (id == null) {id = generateSessionId();}session.setId(id);// 这里会将Session添加到ConcurrentHashMap中sessionCounter++;//将创建时间添加到LinkedList中,并且把最先添加的时间移除//主要还是方便清理过期SessionSessionTiming timing = new SessionTiming(session.getCreationTime(), 0);synchronized (sessionCreationTiming) {sessionCreationTiming.add(timing);sessionCreationTiming.poll();}return session
}

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

protected Map<string, session> sessions = new ConcurrentHashMap&lt;&gt;();

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

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

Token

Session是将要验证的信息存储在服务端,并以SessionId和数据进行对应,SessionId由客户端存储,在请求时将SessionId也带过去,因此实现了状态的对应。而Token是在服务端将用户信息经过Base64Url编码过后传给在客户端,每次用户请求的时候都会带上这一段信息,因此服务端拿到此信息进行解密后就知道此用户是谁了,这个方法叫做JWT(Json Web Token)。

Token相比较于Session的优点在于,当后端系统有多台时,由于是客户端访问时直接带着数据,因此无需做共享数据的操作。

Token的优点

  1. 简洁:可以通过URL,POST参数或者是在HTTP头参数发送,因为数据量小,传输速度也很快
  2. 自包含:由于串包含了用户所需要的信息,避免了多次查询数据库
  3. 因为Token是以Json的形式保存在客户端的,所以JWT是跨语言的
  4. 不需要在服务端保存会话信息,特别适用于分布式微服务

JWT的结构

实际的JWT大概长下面的这样,它是一个很长的字符串,中间用.分割成三部分

JWT是有三部分组成的

Header

是一个Json对象,描述JWT的元数据,通常是下面这样子的

{"alg": "HS256","typ": "JWT"
}

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 http://api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。

Payload

Payload部分也是一个Json对象,用来存放实际需要传输的数据,JWT官方规定了下面几个官方的字段供选用。

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

当然除了官方提供的这几个字段我们也能够自己定义私有字段,下面就是一个例子

{"name": "xiaoMing","age": 14
}

默认情况下JWT是不加密的,任何人只要在网上进行Base64解码就可以读到信息,所以一般不要将秘密信息放在这个部分。这个Json对象也要用Base64URL 算法转成字符串

Signature

Signature部分是对前面的两部分的数据进行签名,防止数据篡改。

首先需要定义一个秘钥,这个秘钥只有服务器才知道,不能泄露给用户,然后使用Header中指定的签名算法(默认情况是HMAC SHA256),算出签名以后将Header、Payload、Signature三部分拼成一个字符串,每个部分用.分割开来,就可以返给用户了。

HS256可以使用单个密钥为给定的数据样本创建签名。当消息与签名一起传输时,接收方可以使用相同的密钥来验证签名是否与消息匹配。

Java 中如何使用 Token

上面我们介绍了关于 JWT 的一些概念,接下来如何使用呢?首先在项目中引入 jar 包。

compile('io.jsonwebtoken:jjwt:0.9.0')

然后编码如下。

// 签名算法 ,将对token进行签名
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 通过秘钥签名JWT
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("SECRET");
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
Map<string,object> claimsMap = new HashMap&lt;&gt;();
claimsMap.put("name","xiaoMing");
claimsMap.put("age",14);
JwtBuilder builderWithSercet = Jwts.builder().setSubject("subject").setIssuer("issuer").addClaims(claimsMap).signWith(signatureAlgorithm, signingKey);
System.out.printf(builderWithSercet.compact());

发现输出的 Token 如下。

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwibmFtZSI6InhpYW9NaW5nIiwiYWdlIjoxNH0.3KOWQ-oYvBSzslW5vgB1D-JpCwS-HkWGyWdXCP5l3Ko

此时在网上随便找个 Base64 解码的网站就能将信息解码出来。

总结

相信大家看到这应该对 Cookie、Session、Token 有一定的了解了,接下来再回顾一下重要的知识点。

  • Cookie 是存储在客户端的
  • Session 是存储在服务端的,可以理解为一个状态列表。拥有一个唯一会话标识 SessionId。可以根据 SessionId 在服务端查询到存储的信息。
  • Session 会引发一个问题,即后端多台机器时 Session 共享的问题,解决方案可以使用Spring提供的框架。
  • Token 类似一个令牌,无状态的,服务端所需的信息被 Base64 编码后放到 Token 中,服务器可以直接解码出其中的数据。

转自:学无数的程序员

cookie代码加时间多久出现一次_一文彻底搞懂Cookie、Session、Token到底是什么相关推荐

  1. cookie代码加时间多久出现一次_恶意代码分析 丨 一个毫无套路的咸鱼诈骗网站...

    在一个百无聊赖的周三下午,还有半个钟头就要下班了,这时候赶紧准备一下,工作收收尾,我们的口号是在5点30准时打卡下班.在一切都收拾妥当发现还有20分钟,无聊的打开论坛决定水水贴,然后看到了一篇关于闲鱼 ...

  2. 访问网址 token的格式_一文彻底搞懂Cookie、Session、Token到底是什么

    欢迎关注文章系列 ,关注我 <提升能力,涨薪可待> <面试知识,工作可待> <实战演练,拒绝996> 如果此文对你有帮助.喜欢的话,那就点个赞呗,点个关注呗! Co ...

  3. cookie代码加时间多久出现一次_JavaWeb——Cookie详解

    目录 一.会话二.保存会话的两种技术1.代码:2.删除Cookie3.中文数据传递 一.会话 会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话.有状态 ...

  4. 一文彻底搞懂Cookie、Session、Token到底是什么

    作者:不学无数的程序员 原文链接:https://juejin.im/post/5de4c3c76fb9a071b86cc482 Cookie 夏洛:大爷,楼上322住的是马冬梅家吧? 大爷:马都什么 ...

  5. 第八十五期:一文彻底搞懂cookie和session

    在Web发展史中,我们知道浏览器与服务器间采用的是 http协议,而这种协议是无状态的,所以这就导致了服务器无法知道是谁在浏览网页,所以为了解决这一问题,先后出现了四种技术,分别是隐藏表单域,URL重 ...

  6. 彻底搞懂Cookie、Session、JWT和Token

    文章目录 引入:http是一个无状态协议?怎么解决呢? 一.Cookie和Session 1.1 cookie 注意事项: 1.2 cookie 重要的属性 1.3 session 注意事项: 1.4 ...

  7. 一文搞懂cookie、session、token、jwt、OAuth

    文章目录 0 测试环境 1 cookie 1.1 概念 1.2 使用flask设置cookie 1.3 浏览器端访问 1.4 设置简单cookie 1.5 给cookie设置一些属性 1.6 浏览器操 ...

  8. 面试题:彻底搞懂 Cookie 和 Session

    我在做面试官的时候,曾经问过很多朋友这个问题: Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等. ...

  9. postman怎么传session_Day 47: 不搞懂Cookie和session誓不罢休

    Hello大家好!我是Cathy海希,今天是我学习编程的第47天. 欢迎同时关注我的Youtube&B站?Cathy海希TV 今天后知后觉地发现方方老师有在知乎上提及跟我相关的内容,简直太荣幸 ...

最新文章

  1. SpringBoot (七) :SpringBoot 整合dubbo
  2. vue-router点击切换路由报错
  3. jar打包 剔除第三方依赖以及它的依赖_maven打包成第三方jar包且把pom依赖包打入进来的方法...
  4. centos7 安装python3.7.1(亲测下面的安装依赖包)
  5. 阿里巴巴开源项目:分布式数据库同步系统otter(解决中美异地机房)
  6. MFC访问阿里云Oss平台
  7. HashSet 和 TreeSet 及 Map 集合的简单方法,含程序。
  8. vue-cli3.0项目的安装、创建和启动
  9. 使用xp_readerrorlog命令读取SQL Server错误日志
  10. 在Ubuntu上搭建TensorFlow
  11. 小白能读懂的 《手把手教你学DSP(TMS320X281X)》第六章 F2812的存储器映像
  12. Easy EDA:在线创客软件服务是未来的趋势 | 雷锋网
  13. RiceQuant开源项目Rqalpha运行演示策略的错误“ERROR 'figure' is an unknown keyword argument”...
  14. 消息推送之百度云推送Android集成与用法
  15. 干货】最详细、最完美、可以上下左右移动的表格布局,仿同花顺自选列表,老虎证券财报列表,欢迎 Start、Fork
  16. Mysql的分组函数
  17. 单身程序猿的七夕应该怎么过?
  18. 我能成为一名布道师吗?
  19. 六一快乐!管她几岁,快乐万岁!
  20. 二代测序技术之illumina测序技术原理简介

热门文章

  1. SilverlightComponent for ExtJS
  2. Elasticsearch查询之term/match解析
  3. [android] 帧动画和补间动画
  4. Nginx 部署 Django
  5. [转]如何使用WinPE硬盘安装Windows XP
  6. 宇斯盾助中厚实现TurboERP远程应用
  7. iOS开发笔记 2、Cocoa简明
  8. PGA自动管理原理深入分析及性能调整
  9. forms角色验证,以普通用户身份登陆管理页面先弹出警告信息窗口
  10. python scrapy同时执行spiders多个爬虫