Cookie、Session

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-07-30

session的使用

cookie:在浏览器中保存一些数据,每次请求都会带过来,保存在客户端。不安全,空间有限(4k),需要注意的是,后台采用的会话期cookie只会在浏览器退出的时候删除,而不会在标签页被关闭时删除。

session:数据保存在服务端,是基于cookie实现的,往cookie中写入一个session_id,服务器利用session_id找到session文件读取、写入等等一系列的操作,隐患:session劫持,session_id 存放在客户端,可以被查看和更改,别人可以通过获取你的session_id以你的身份访问服务器。

const express = require('express');
const cookieParser = require('cookie-parser');
var server = express();

server.use(cookieParser());

server.use('/', function (req, res) {
  // 使用cookieParser中间件,可以直接读取前端带过来的cookie
  console.log(req.cookies);

  // 向前端发送cookie
  // 过期时间为30天, key 是 user ,value是jack
  // path指谁能够用这个cookie,localhost:8081/aaa下才有cookie。
  // 上级路径可以访问,下级路径或者同级路径无法访问
  res.cookie('user', 'jack', {path: '/aaa', maxAge: 30*24*3600*1000}) // 毫秒为单位
  res.send('ok')
})

server.listen(8081);

对cookie加签:

// cookie的常规操作 可以使用cookie-encrypter中间件进行cookie的加签
const express = require('express');
const cookieParser = require('cookie-parser');

var server = express();

server.use(cookieParser('jsajsdklja')); // 传入密钥,解签cookie

server.use('/', function (req, res) {
  // 发送cookie
  res.cookie('user', 'jack', {signed: true}); // 使用签名,原文还是看得见,但是可以防止修改

  // 签完名之后的cookie 获取的时候,也是签完名之后的值,而不是原本的user: jack
  // 因为cookie本来空间有限,加签后会增加体积,所以,不是所有数据都要加签,只加签重要的字段
  // 下面是获取不同cookie的方法 
  console.log('签名cookie', req.signedCookies); // 获取签过名的cookie 是解签过的
  console.log('无签名cookie', req.cookies); // 获取未签名的cookie

  // 删掉cookie
  res.clearCookie('user')

  res.send('ok')
})

server.listen(8081);

使用session:

const express = require('express');
const cookieSession = require('cookie-session');
const cookieParser = require('cookie-parser');

var app = express();

app.use(cookieParser());
// 必须先使用cookieParser来解析
app.use(cookieSession({
  name: 'test_key', // session_id的key 默认为session
  keys: ['sdas','mklj','kowi'], // 必选的参数,添加密钥,可以有多个,循环使用更加安全
  maxAge: 20*60*1000 // 有效期,越短越安全,但是太短的话用户会经常需要重做登录
})); 

app.use('/', function (req, res) {
  // 记录访问次数
  // 设置cookie
  if(req.session['count'] == null) {
    req.session['count'] = 1;
  } else {
    req.session['count']++;
  }

  console.log(req.session['count']);

  // 删除session
  // delete req.session

  res.send('ok');
})

app.listen(8081)

关于cookie

http请求是无状态的,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录。

为了解决客户端与服务端会话同步问题。这便引出了session的概念。

服务器第一次接收到请求时,如果在请求头中找不到sessionId的cookie就会开辟了一块Session空间(创建了Session对象),同时生成一个Session id,并通过响应头的Set-Cookie:“JSESSIONID=XXXXXXX”命令,向客户端发送要求设置cookie的响应; 客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX的cookie信息,该cookie的过期时间为浏览器会话结束;

接下来客户端每次向同一个网站发送请求时,浏览器会自动去终端内存中找到对应域名下的cookie信息,请求头都会带上该cookie信息(包含Session id); 然后,服务器通过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,得到此次请求的Session id,因此判断是否是同一个客户端。

浏览器基于域存储cookie,不论这个请求的源是什么都会主动带上请求链接所在域下的cookie信息。比如:在 abc.com.cn 域名下 请求 baidu.com.cn 的接口,只要本地有 baidu.com.cn 域名下的cookie数据,这个请求就会携带上该cookie。

在谷歌浏览器 76+ 版本的请求头中,可以看到 Sec-Fetch-Site 这个属性,这个属性的值明确的表明了发起源和请求源的关系。有

  • Sec-Fetch-Site: cross-site 跨站请求
  • Sec-Fetch-Site: same-origin 同源请求
  • Sec-Fetch-Site: same-site 同站请求
  • Sec-Fetch-Site: none 此请求与任何上下文(如站点、源或框架)都不相关。当用户通过直接在地址栏中输入URL、打开书签或将文件拖放到浏览器窗口中来启动此请求时,可能会发生这种情况。

Same-Site可以设置如下三个参数:

  • Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。比如说假如 b.com 设置了cookie,则只用 b.com下的页面请求可以携带 cookie 访问 b.com的服务器

  • Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

  • None,对于cookie的使用无限制,随便使用。如果将其设为None,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。