内存Cookie和硬盘Cookie
。
没有设置过期时间
,默认情况下cookie是内存cookie,在关闭浏览器时会自动删除;有设置过期时间 (max-age=过期时间)
,并且过期时间不为0或者负数的cookie,是硬盘cookie,需要手动或者到期时,才会删除;会话cookie
,也就是在浏览器关闭时会自动被删除expires
:设置的是Date.toUTCString(),设置格式是;expires=date-in-GMTString-format;max-age
:设置过期的秒钟,;max-age=max-age-in-seconds (例如一年为606024*365);const koa = require('koa');
const koaRouter = require('@koa/router');
const app = new koa()
/**
* @description:
* @param {type} 服务端设置cookie
* @param {type} 客户端(游览器)获取服务器设置的cookie,并且做一个保存
* @param {type} 在同一个作用域下进行访问(域名/路径), 会在动携带cookie
* @param {type} 服务器可以通过客户端携带的cookie验证用户的身份
* @return:
*/
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/login', (cxt, next) => {
// 服务器设置会话cookie
cxt.cookies.set('slogin', 'ikun', {
maxAge: 60 * 1000
})
cxt.body = '登录成功'
next()
})
userRouter.get('/list', (cxt, next) => {
// 当上个接口登录成功后 这个cookie会自动携带
const cookie = cxt.cookies.get('slogin')
console.log(cookie);
if (cookie) {
cxt.body = cookie
}
})
app.use(userRouter.routes())
app.listen(9000, () => {
console.log('服务器启动成功~');
})
同时在发送HTTP请求时,发现游览器将我们的cookie都进行了携带(注意:游览器只会携带在当前请求的url中包含了该cookie中path值的cookie),并且是以key:value的形式进行表示的。多个cookie用;进行隔开。
- Session的工作流程:当浏览器访问服务器并发送第一次请求时,
服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对
,然后将 key(cookie)返回到浏览器(客户端),浏览器下次再访问时,携带 key(cookie),找到对应的 session(value),用户的信息都保存在 session 中
。
const koa = require('koa');
const koaSession = require('koa-session');
const koaRouter = require('@koa/router');
const app = new koa()
// npm i koa-session
const session = koaSession({
key: 'sessionId',
httpOnly:true, // 不允许通过JS获取cookie
maxAge:5*1000, // 过期时间
rolling:true, // 每次响应时,刷新session的有效期
signed:true // 加密签名认证,防止数据被篡改,必传
},app)
app.keys=['aaa'] // 加盐操作 ,双层验证
app.use(session)
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/login', (cxt, next) => {
cxt.session.slogin='ikun'
cxt.body = '登录成功'
})
userRouter.get('/list', (cxt, next) => {
const cookie = cxt.session.slogin
console.log(cookie);
if (cookie) {
cxt.body = cookie
}else{
cxt.body='没有权限访问'
}
})
app.use(userRouter.routes())
app.listen(9000, () => {
console.log('服务器启动成功~');
})
cookie 数据存放在客户端浏览器上,session 数据放在服务器上。
cookie 不是很安全,是明文传递的,所以存在安全性的问题;
session 会在一定时间内保存在服务器上。访问增多会占用服务器的性能,若要减轻服务器性能问题,应使用 cookie。
单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
对于浏览器外的其他客户端(比如iOS、Android),必须手动的设置cookie和session;
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
JWT生成的Token由三部分组成:
header 用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
payload
signature
secretKey
,通过将前两个的结果合并后进行HS256的算法;JWT原理文章参考
const koa = require('koa');
const jwt = require('jsonwebtoken');
const koaRouter = require('@koa/router');
const app = new koa()
// npm i jsonwebtoken
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/login', (cxt, next) => {
// 1. 颁发token
const payload = { name: 'admin', password: 123456 }
const secretKey = "aaaaaaaaaaaaaa"
const token = jwt.sign(payload, secretKey, {
expiresIn:30
})
cxt.body={
code:200,
token:token,
message:'登录成功'
}
})
userRouter.get('/list', (cxt, next) => {
// 获取客户端携带过来的token
const authorization=cxt.headers.authorization
const token=authorization.replace('Bearer','')
console.log(token);
// 2. 验证token
try {
const result=jwt.verify(token,escretkey)
console.log(result);
} catch (error) {
cxt.body = 'token过期,没有权限访问,请重新登录'
}
})
app.use(userRouter.routes())
app.listen(9000, () => {
console.log('服务器启动成功~');
})
私钥生成签名
, JWT 的使用方获取公钥以验证签名
。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)
openssl
genrsa -out private.key 2048
rsa -in private.key -pubout -out public.key
const koa = require('koa');
const jwt = require('jsonwebtoken');
const fs = require('fs');
const koaRouter = require('@koa/router');
const app = new koa()
const pubilcKey = fs.readFileSync('./keys/public.key')
const reivateKey = fs.readFileSync('./keys/private.key')
const userRouter = new koaRouter({ prefix: '/users' })
userRouter.get('/login', (cxt, next) => {
// 1. 颁发token
const payload = { name: 'admin', password: 123456 }
const token = jwt.sign(payload, reivateKey, {
// 修改加密方式 HS256改为RS256加密
expiresIn: 60, algorithm: 'RS256'
})
cxt.body = {
code: 200,
token: token,
message: '登录成功'
}
})
userRouter.get('/list', (cxt, next) => {
// 获取客户端携带过来的token
const authorization = cxt.headers.authorization
const token = authorization.replace('Bearer', '')
// 2. 验证token
try {
const result = jwt.verify(token, pubilcKey, {algorithms: ['RS256'] })
console.log(result);
} catch (error) {
cxt.body = 'token过期,没有权限访问,请重新登录'
}
})
app.use(userRouter.routes())
app.listen(9000, () => {
console.log('服务器启动成功~');
})