node 实现鉴权
分类:javascript
实现方式
- cookie :所有数据通过客户端cookie保存,不安全
- session+cookie :两者结合,cookies只记录id
- token :jwt
- oauth
- SSO
1.session/cookie
优点:统一管理,数据存服务端,比纯cookie安全
缺点:服务器有状态,跨域是问题
- 客户端请求服务器,第一次token为空,
- 服务器接收到请求,找不到sid,创建一个然后返回
- 客户端通过cookie保存sid,并且第二次请求时候带上,
- 服务器接收到sid,在session[sid] 记录相关的信息,并且返回
- 后续的所有操作都是基于sid,通过键值方式获取session[sid]对应的所有数据
- 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)
- 摘要 如: 小李子 x0l0z
- 不固定长度生成固定长度的结果 如:放到沙发上 -> 123456 , 但是 -> 234567 ,同样是6位
- 雪崩效应 一点点的变化都会导致巨变,比如 张学友 和 张学朋 加密后 两者的结果可以是完全不同
koa-session 的签名原理
- signed: true // 签名 打开
- app.keys = ['some secret']//加盐的方式 生成签名
cookies 生成sid 和 加密之后的sid.sig,每次请求都会匹配cookie的sess.sig和服务器计算之后sess.sig是否一致
- sess.sig === hash(sid + ['some secret']) ?'成功':'失败'
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)
token
优点:
- 无状态,
- 跨域,
- 能把json对象通过jwt转成token ,并且还原json对象
- 加密安全