cookie原理
服务端在Header Set-Cookie,然后客户端会自动存取下来(cookie中可以看到)
下次请求,请求头会携带cookie传给后端
const http = require('http')
http
.createServer((req,res)=>{
if(req.url === '/favicon.ico'){
res.end('')
return
}
//观察cookie存在
console.log('cookie:',req.headers.cookie)
//设置cookie
res.setHeader('Set-Cookie','cookie1=aaa')
res.end('hello cookie')
})
.listen(3000)
cookie缺点
因为有上面的缺点,不适合做鉴权,需要用session来配合
session原理
浏览器首次访问,生成uid保存在服务端session中,且将uid存储于cookie
下次访问,根据uid对请求进行认证
const http = require('http')
const session = {
}
http
.createServer((req,res)=>{
//观察cookie是否存在
console.log('cookie',req.headers.cookie)
//存储一对键值对
const sessionKey = 'uid'
const cookie = req.headers.cookie
if(cookie&&cookie.indexOf(sessionKey)!=-1){
//下次访问
res.end('Come Back')
//使用正则解析是否存在之前的cookie
const pattern = new RegExp(`${
sessionKey}=([^;]+);?\s*`)
const uid = pattern.exec(cookie)[1]
console.log('session',uid,session,session[uid])
}else{
//第一次访问
//设置键值对的值,用你需要的规则,这儿用随机数代替
const uid = (Math.random()*9999999999).toFixed()
res.setHeader('Set-Cookie',`${
sessionKey}=${
uid};`)
//真正的数据
session[uid] = {
name:'admin'}
res.end('hello admin')
}
res.end('hello session')
})
.listen(3000)
session优点
通过koa-session中间件来实现
const koa = require('koa')
const app = new koa()
const session = require('koa-session')
//签名key keys作用 用来对cookie进行签名
app.keys = ['some secret']
//配置项
const SESS_CONFIG = {
key: "sess", //cookie链名
maxAge: 86400000, // 有效期,默认一天
httpOnly: true, // 只能用于http传输,仅服务器修改,提高安全性
signed: true // 签名cookie,如秘钥
}
//注册
app.use(session(SESS_CONFIG, app))
//测试
app.use(ctx => {
if(ctx.path === '/favicon.ico') return
//获取
let n = ctx.session.count || 0
//设置
ctx.session.count = ++n
ctx.body = '第'+n+'次访问'
})
app.listen(3000)
上面的session存储于变量(内存)中,可能会遇到下面的一些问题
所以通常情况下需要将session进行全局存储,一般将其存在redis中
redis介绍
一个高性能的key-value数据库
redis缓存产品的三个特点
const redis = require('redis')
//连接redis
const client = redis.createClient(6379,'localhost')
//使用事件发射器,检测错误
client.on("error", function (err) {
console.log("Error " + err);
});
//设置
client.set('key','value')
//拿取
client.get('key',(err,v)=>{
if(err) throw err;
console.log('redis get ', v)
})
如果报下面的错误,则表示reids-server未启动
Error Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
koa-redis使用
安装
npm i -S koa-redis
const koa = require('koa')
const app = new koa()
const session = require('koa-session')
const redisStore = require('koa-redis')
const redis = require('redis')
const redisClient = redis.createClient(6379,'localhost')
const wrapper = require('co-redis')
const client = wrapper(redisClient)
//签名key keys作用 用来对cookie进行签名
app.keys = ['some secret']
//配置项
const SESS_CONFIG = {
key: "sess", //cookie链名
maxAge: 86400000, // 有效期,默认一天
httpOnly: true, // 仅服务器修改
signed: true, // 签名cookie
store: redisStore({
client}) // 指定存储则会按照你要求的去存储,否则会默认存储到内存中
}
//注册
app.use(session(SESS_CONFIG, app))
app.use(async (ctx,next) => {
const keys = await client.keys('*')
keys.forEach(async key => console.log(await client.get(key)))
await next()
})
//测试
app.use(ctx => {
if(ctx.path === '/favicon.ico') return
//获取
let n = ctx.session.count || 0
//设置
ctx.session.count = ++n
ctx.body = '第'+n+'次访问'
})
app.listen(3000)
1、服务端有状态,需要去进行相关存储,若服务器断了,就会刷新内存,重连之后下次请求就会出现问题
2、基于cookie传送,cookie是基于浏览器的,不够灵活。如APP、跨域等其他情况会受限