http 是一种无状态的协定,每一个申请都是独立的,即便同一个页面向服务器发送屡次申请,服务器也无奈辨别是不是同一用户,所以这个时候能够借助于 cookie 来做身份认证,当用户登录胜利,服务器为浏览器设置 cookie,而在前面的申请当中,浏览器发送申请的时候,就会携带 cookie,需注意的是,cookie 须要同源的申请下才会发送。
设置 cookie 的时候还有以下值属性能够进行抉择,别离是过期工夫和作用域,没有设置过期工夫,cookie 的生命周期仅为会话阶段,敞开浏览器即被删除,通过 max-age 或者 expires 设置,cookie 的生命周期为有效期内,超出有效期则被删除,作用域可设置 domain 和 path,domain 代表指定哪些主机能够接管 cookie,没有设置的时候默认 origin,仅以后域名无效,设置后以后域名和子域名都可用,path 用于指定主机下哪个门路能够承受 cookie。
浏览器端通过 document.cookie 来获取和设置 cookie,当须要在浏览器使 cookie 生效,则能够设置 max-age=0
document.cookie = 'name=alice;max-age=5' // max-age 在浏览器端的单位为秒
在服务器端,通过 nodejs 中 http 模块设置响应头信息 setCookie,第二次申请则会在申请头中携带 cookie,如果对 nodejs 不太熟悉,能够参考这一篇文章,nodejs 中如何应用 http 创立一个服务
const http = require('http')
const server = http.createServer((req, res) => {res.setHeader('Set-Cookie', ['age=16;max-age=20000'])
// max-age 在 nodejs 的单位为毫秒
res.end('cookie')
})
koa 中通过 ctx.cookies.set 和 ctx.cookies.get 来别离设置和获取 cookie,以下代码示意,当拜访 localhost:7000/login 的时候,服务器为浏览器设置一个 cookie,当拜访 localhost:7000/user 的时候,服务器获取浏览器的 cookie。
如果对 koa 还不太熟悉,能够参考这一篇文章,让 nodejs 开启服务更简略 –koa 篇
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()
router.get('/login', (ctx, next) => {
ctx.cookies.set('wheater', 'sunny', {maxAge: 60*1000})
ctx.body = 'set cookie'
})
router.get('/user', (ctx, next) => {const cookie = ctx.cookies.get('wheater')
ctx.body = cookie
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(7000, ()=>{console.log('开启服务')})
应用 nodejs 中的 http 模块对申请进行响应须要本人解决简单逻辑,通过 koa 能够简化很多操作,比方 koa 就主动加上了 HttpOnly 的属性
以上存储在 cookie 中的数据都是以明文的模式,十分的不平安,真正在理论利用时,须要将用户信息进行加密解决,这时候能够思考应用 session,session 也是给浏览器填充 cookie 值,但它能够为填充的 cookie 进行加密解决
const Koa = require('koa')
const Router = require('koa-router')
const Session = require('koa-session')
const app = new Koa()
const router = new Router()
// signed: true 减少一个 sessionid 的签名文件 sessionid.sig
const session = Session({
key: 'sessionId',
maxAge: 60 * 1000,
signed: true
}, app)
app.keys = ['alice']
app.use(session)
router.get('/login', (ctx, next) => {
const id = 1;
const name = 'lucy'
ctx.session.user = {id, name}
ctx.body = 'set session'
})
router.get('/user', (ctx, next) => {ctx.body = ctx.session.user // { id: 1, name: 'lucy'}
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(7000, () => {console.log('开启服务') })
session 以 base64 编码的模式进行存储,能够被解码,也并不齐全平安,所以通过 signed: true 设置密钥,使减少一个加密后的 sessionid.sig,这样服务器在获取 cookie 中设置的 session 数据就会对数据的真实性进行校验
以上 cookie 和 session 能够用于身份校验,但这种形式存在以下问题:
1、cookie 在每个申请的时候都会被携带,无形之中减少了带宽
2、cookie 只有 4kb 的容量,对于简单需要可能不够用
3、在浏览器外的其余客户端,cookie 并不会被动携带,须要手动设置 cookie 和 session,所以不同端在解决 cookie 上存在差别
4、对于分布式系统和服务器集群中如何能够保障其余零碎也能够正确的解析 session 也存在问题,像 java 中每台服务器获取 session 的密钥都不一样
基于以上问题,目前越来越多的开发者会应用 token 来进行鉴权,下一篇文章中认真介绍 token 如何做到身份校验~