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.sigconst 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 如何做到身份校验~