session vs token 的具体使用及特性
session
- session思想
- 客户端输入 用户名跟密码 请求登录
- 服务端收到请求,去数据库验证用户名和密码
- 验证成功后,服务端种一个 cookie 或者发一个字符串到客服端,同时服务器存储一个 session
- 客服端收到响应后,把收到的字符串存储到 cookie 中
- 客服端每次向服务端请求资源都会自动携带 cookie
- 服务端收到请求后去验证 cookie 和 session ,验证成功就向客户端返回数据
- 注意:
- session储存位置:服务器内存 / 磁盘 / 数据库
- session存储内容:id、存储时间,用户名等说明信息
- cookie 每次发送请求 客户端会自动携带,而 localStorage 需要手动携带
session 使用
-
npm 下载 cookie-session 包
-
引入 cookie-session 包
let cookieSession = require('cookie-session')
-
配置 中间件
server.use(cookieSession({ name: 'myCookie', // 保存到客户端的 cookie 名字 默认是: express:ress keys: ['ab','cd'], // 必传参数,代表加密层级 maxAge: 1000 // 单位是 ms , 表示 cookie 的过期时间 }))
-
种 cookie 和 备份 session
req.session.key = value
-
拿 cookie ,对比 session
req.session.key // 存在结果就是对应的值, 不存在结果就是 undefined
-
删除 cookie 和 session
// 方法一: delete req.session.key // 方法二: req.session.key = undefined
// 例子
let express = require('express')
let cookieSession = require('cookie-session')
let server = express() // 创建服务
server.listen(3000)
// 使用 cookieSession 这个中间件
server.use(cookieSession({
name: 'myCookie',
keys: ['aaa','bbb'], // 加密层级
maxAge: 1000*10 // 10 秒后过期
}))
server.post('./login', (req, res) => {
// 1. 验证登录信息是否正确
// 2. 如果正确, 种 cookie,备份 session
req.session.userInfo = 'userID'
...
})
server.get('./index', (req, res) => {
// 查看 是否存在用户的 cookie, 不存在结果就是 undefined
let cookie = req.session.userInfo // 存储了什么,拿到的就是什么
if(cookie){
// 说明已经登录过
...
}else{
// 尚未登录或者登录时效
...
})
token
- token 思想
- 客户端发送 用户名 和 密码 请求登录
- 服务端收到请求后,去验证 用户名和密码
- 验证成功后,服务端会签发一个 token(加了密的字符串),并把这个 token 响应给客户端
- 客户端收到 token 后,把它存储起来,存储在 cookie 或者 local Storage 里面
- 客服端每次向服务端发送请求时,都带着服务端签发的 token
- 服务端收到请求后,去验证客户端带来的 token;验证成功后,就向客户端返回请求的数据
- 服务端 只签发 token, 不保存 ,token 保存在客户端,token 的删除 也是需要 客户端负责删除
token 使用
-
引入 jsonwebtoken 这个第三方模块
// 先使用 npm i jsonwebtoken -S 下载这个模块 let jwt = require('jsonwebtoken') // 引入模块
-
生成 token 签名
// 语法:jwt.sign(payload, secretOrPrivateKey, [options, callback]) 也可同步返回 token let token = jwt.sign( {username:req.query.username}, // 加密的内容 必填 "sz1920", // 加密规则 必填 {expiresIn: 60} // 可选参数 过期时间 )
-
校验 token
// 语法:jwt.verift(token, secretOrPublicKey, [options, callback]) let token = req.query.token || req.body.token || req.headers.token jwt.verift(token, "sz1920", (err, decode) => { }) // 解析成功说明用户登录过
// 例子
// 引入 express 模块
const express = require('express')
// 引入 jsonwebtoken 模块
const jwt = require('jsonwebtoken')
// 引入 body-parser 模块
const bodyParser = require('body-parser')
// 创建 服务 对象
const server = express()
// 使用 bodyParser 这个中间件
server.use(bodyParser())
// 监听端口
server.listen(3000, () => {
console.log("3000 端口正在被监听哦。。。")
})
server.post('/login', (req, res) => {
// 1. 验证用户传来的 登录信息是否匹配
// 2. 如果成功 服务器 签发一个 token
let token = jwt.sign(
{username: req.body.username }, // 需要加密的内容 必填
"sz1920", // 加密规则 必填
{expiresIn: 60} // 设置过期时间 60 秒 选填
)
// 3. 给客户端响应,返回数据,并携带 token
res.send({
err: 0,
token: token,
data: [1,2,3]
})
})
server.get('/index', (req, res) => {
// 验证 客户端传递过来的 token
let token = req.query.token || req.body.token || req.headers.token
jwt.verify(token, 'sz1920', (err, decode) => {
if(decode){ // token 存在 直接返回数据
res.send({
err: 0,
data: [decode,{message: "已是登录状态"}]
})
}else{ // token 失效
res.send({
err: 1,
data: [{message: "登录失效"}]
})
}
})
})
- token 与 session 的区别
- session 存储在服务端,token 存储在 客户端
- session 可以被 CSRF 攻击,token 不会被攻击
- 所以 token 安全性 更高
- token 能避免 session 带来的服务端的压力和服务端粘性问题
session vs token
session | token | |
---|---|---|
服务端保存用户信息 | √ | × |
避免CSRF攻击 | × | √ |
安全性 | 一般 | 高 |
多服务器粘性问题 | 存在 | 不存在 |
- 什么是多服务器粘性问题
- 当在应用中进行 session的读,写或者删除操作时,会有一个文件操作发生在操作系统的temp 文件夹下,至少在第一次时。假设有多台服务器并且 session 在第一台服务上创建。当你再次发送请求并且这个请求落在另一台服务器上,session 信息并不存在并且会获得一个“未认证”的响应。我知道,你可以通过一个粘性 session 解决这个问题。然而,在基于 token 的认证中,这个问题很自然就被解决了。没有粘性 session 的问题,因为在每个发送到服务器的请求中这个请求的 token 都会被拦截。
关键字: session token 多服务器粘性问题