node 实现鉴权 cookie session

·  阅读 367

实现方式

  1. cookie :所有数据通过客户端cookie保存,不安全
  2. session+cookie :两者结合,cookies只记录id

1.session/cookie

  • 优点:统一管理,数据存服务端,比纯cookie安全
  • 缺点:服务器有状态,跨域是问题,不支持分布式部署

image.png

  1. 客户端请求服务器,第一次token为空,
  2. 服务器接收到请求,找不到sid,创建一个然后返回
  3. 客户端通过cookie保存sid,并且第二次请求时候带上,
  4. 服务器接收到sid,在session[sid] 记录相关的信息,并且返回
  5. 后续的所有操作都是基于sid,通过键值方式获取session[sid]对应的所有数据
  6. session有过期日期,过期了会删除
const http = require('http')
const session = {}
http.createServer((req, res) => {
    const sessionKey = 'sid'

    if (req.url === '/favicon.ico') {
        return
    } else {
        const cookie = req.headers.cookie
        if (cookie && cookie.indexOf(sessionKey) > -1) {
            res.end('Come Back')
            console.log('cookie:', req.headers.cookie)
            // 简略写法未必具有通用性
            const pattern = new RegExp(`${sessionKey}=([^;]+);?\s*`)
            const sid = pattern.exec(cookie)[1]
            console.log('session:', sid, session, session[sid])
        } else {
            const sid = (Math.random() * 9999999).toFixed()
            res.setHeader('Set-Cookie', `${sessionKey}=${sid}`)
            session[sid] = { name: 'laowang' }
            res.end('hello cookie')
        }
    }
}).listen(3000)
复制代码

2.koa+ redis实现session

hash原理 (sha,md5)

  1. 摘要 如: 小李子 x0l0z
  2. 不固定长度生成固定长度的结果 如:放到沙发上 -> 123456 , 但是 -> 234567 ,同样是6位
  3. 雪崩效应 一点点的变化都会导致巨变,比如 张学友 和 张学朋 加密后 两者的结果可以是完全不同

koa-session 的签名原理

  1. signed: true // 签名 打开
  2. app.keys = ['some secret']//加盐的方式 生成签名

cookies 生成sid 和 加密之后的sid.sig,每次请求都会匹配cookie的sess.sig和服务器计算之后sess.sig是否一致

  • sess.sig === hash(sid + ['some secret']) ?'成功':'失败'

image.png

index.js

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)

app.keys = ['some secret']//加盐的方式 生成签名

const SESS_CONFIG = {
    key: 'kkb:sess', // 名
    // maxAge: 8640000, // 有效期
    // httpOnly: true, // 服务器有效
    // signed: true // 签名 打开
    store: redisStore({ client })
}

app.use(session(SESS_CONFIG, app))

app.use(ctx => {
    // 查看redis
    redisClient.keys('*',(err,keys) => {
        console.log('keys:',keys)
        keys.forEach(key => {
            redisClient.get(key, (err,val) => {
                console.log(val)
            })
        })
    })

    if (ctx.path === '/favicon.ico') return
    let n = ctx.session.count || 0
    ctx.session.count = ++n
    ctx.body = '第' + n + '次访问'
})
app.listen(3000)

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ee6d5f7d3be94076bf0d1bfbd412887d~tplv-k3u1fbpfcp-watermark.image)
复制代码
分类:
前端
标签: